Paradise Lost
John Milton
Book 1


Of Mans First Disobedience, and the Fruit
Of that Forbidden Tree, whose mortal tast
Brought Death into the World, and all our woe,
With loss of EDEN, till one greater Man
Restore us, and regain the blissful Seat,
Sing Heav'nly Muse, that on the secret top
Of OREB, or of SINAI, didst inspire
That Shepherd, who first taught the chosen Seed,
In the Beginning how the Heav'ns and Earth
Rose out of CHAOS: Or if SION Hill
Delight thee more, and SILOA'S Brook that flow'd
Fast by the Oracle of God; I thence
Invoke thy aid to my adventrous Song,
That with no middle flight intends to soar
Above th' AONIAN Mount, while it pursues
Things unattempted yet in Prose or Rhime.
And chiefly Thou O Spirit, that dost prefer
Before all Temples th' upright heart and pure,
Instruct me, for Thou know'st; Thou from the first
Wast present, and with mighty wings outspread
Dove-like satst brooding on the vast Abyss
And mad'st it pregnant: What in me is dark
Illumine, what is low raise and support;
That to the highth of this great Argument
I may assert th' Eternal Providence,
And justifie the wayes of God to men.

Say first, for Heav'n hides nothing from thy view
Nor the deep Tract of Hell, say first what cause
Mov'd our Grand Parents in that happy State,
Favour'd of Heav'n so highly, to fall off
From their Creator, and transgress his Will
For one restraint, Lords of the World besides?
Who first seduc'd them to that fowl revolt?
Th' infernal Serpent; he it was, whose guile
Stird up with Envy and Revenge, deceiv'd
The Mother of Mankinde, what time his Pride
Had cast him out from Heav'n, with all his Host
Of Rebel Angels, by whose aid aspiring
To set himself in Glory above his Peers,
He trusted to have equal'd the most High,
If he oppos'd; and with ambitious aim
Against the Throne and Monarchy of God
Rais'd impious War in Heav'n and Battel proud
With vain attempt. Him the Almighty Power
Hurld headlong flaming from th' Ethereal Skie
With hideous ruine and combustion down
To bottomless perdition, there to dwell
In Adamantine Chains and penal Fire,
Who durst defie th' Omnipotent to Arms.
Nine times the Space that measures Day and Night
To mortal men, he with his horrid crew
Lay vanquisht, rowling in the fiery Gulfe
Confounded though immortal: But his doom
Reserv'd him to more wrath; for now the thought
Both of lost happiness and lasting pain
Torments him; round he throws his baleful eyes
That witness'd huge affliction and dismay
Mixt with obdurate pride and stedfast hate:
At once as far as Angels kenn he views
The dismal Situation waste and wilde,
A Dungeon horrible, on all sides round
As one great Furnace flam'd, yet from those flames
No light, but rather darkness visible
Serv'd only to discover sights of woe,
Regions of sorrow, doleful shades, where peace
And rest can never dwell, hope never comes
That comes to all; but torture without end
Still urges, and a fiery Deluge, fed
With ever-burning Sulphur unconsum'd:
Such place Eternal Justice had prepar'd
For those rebellious, here their Prison ordain'd
In utter darkness, and their portion set
As far remov'd from God and light of Heav'n
As from the Center thrice to th' utmost Pole.
O how unlike the place from whence they fell!
There the companions of his fall, o'rewhelm'd
With Floods and Whirlwinds of tempestuous fire,
He soon discerns, and weltring by his side
One next himself in power, and next in crime,
Long after known in PALESTINE, and nam'd
BEELZEBUB. To whom th' Arch-Enemy,
And thence in Heav'n call'd Satan, with bold words
Breaking the horrid silence thus began.

If thou beest he; But O how fall'n! how chang'd
From him, who in the happy Realms of Light
Cloth'd with transcendent brightnes didst outshine
Myriads though bright: If he whom mutual league,
United thoughts and counsels, equal hope,
And hazard in the Glorious Enterprize,
Joynd with me once, now misery hath joynd
In equal ruin: into what Pit thou seest
From what highth fal'n, so much the stronger provd
He with his Thunder: and till then who knew
The force of those dire Arms? yet not for those
Nor what the Potent Victor in his rage
Can else inflict do I repent or change,
Though chang'd in outward lustre; that fixt mind
And high disdain, from sence of injur'd merit,
That with the mightiest rais'd me to contend,
And to the fierce contention brought along
Innumerable force of Spirits arm'd
That durst dislike his reign, and me preferring,
His utmost power with adverse power oppos'd
In dubious Battel on the Plains of Heav'n,
And shook his throne. What though the field be lost?
All is not lost; the unconquerable Will,
And study of revenge, immortal hate,
And courage never to submit or yield:
And what is else not to be overcome?
That Glory never shall his wrath or might
Extort from me. To bow and sue for grace
With suppliant knee, and deifie his power
Who from the terrour of this Arm so late
Doubted his Empire, that were low indeed,
That were an ignominy and shame beneath
This downfall; since by Fate the strength of Gods
And this Empyreal substance cannot fail,
Since through experience of this great event
In Arms not worse, in foresight much advanc't,
We may with more successful hope resolve
To wage by force or guile eternal Warr
Irreconcileable, to our grand Foe,
Who now triumphs, and in th' excess of joy
Sole reigning holds the Tyranny of Heav'n.

So spake th' Apostate Angel, though in pain,
Vaunting aloud, but rackt with deep despare:
And him thus answer'd soon his bold Compeer.

O Prince, O Chief of many Throned Powers,
That led th' imbattelld Seraphim to Warr
Under thy conduct, and in dreadful deeds
Fearless, endanger'd Heav'ns perpetual King;
And put to proof his high Supremacy,
Whether upheld by strength, or Chance, or Fate,
Too well I see and rue the dire event,
That with sad overthrow and foul defeat
Hath lost us Heav'n, and all this mighty Host
In horrible destruction laid thus low,
As far as Gods and Heav'nly Essences
Can Perish: for the mind and spirit remains
Invincible, and vigour soon returns,
Though all our Glory extinct, and happy state
Here swallow'd up in endless misery.
But what if he our Conquerour, (whom I now
Of force believe Almighty, since no less
Then such could hav orepow'rd such force as ours)
Have left us this our spirit and strength intire
Strongly to suffer and support our pains,
That we may so suffice his vengeful ire,
Or do him mightier service as his thralls
By right of Warr, what e're his business be
Here in the heart of Hell to work in Fire,
Or do his Errands in the gloomy Deep;
What can it then avail though yet we feel
Strength undiminisht, or eternal being
To undergo eternal punishment?
Whereto with speedy words th' Arch-fiend reply'd.

Fall'n Cherube, to be weak is miserable
Doing or Suffering: but of this be sure,
To do ought good never will be our task,
But ever to do ill our sole delight,
As being the contrary to his high will
Whom we resist. If then his Providence
Out of our evil seek to bring forth good,
Our labour must be to pervert that end,
And out of good still to find means of evil;
Which oft times may succeed, so as perhaps
Shall grieve him, if I fail not, and disturb
His inmost counsels from their destind aim.
But see the angry Victor hath recall'd
His Ministers of vengeance and pursuit
Back to the Gates of Heav'n: The Sulphurous Hail
Shot after us in storm, oreblown hath laid
The fiery Surge, that from the Precipice
Of Heav'n receiv'd us falling, and the Thunder,
Wing'd with red Lightning and impetuous rage,
Perhaps hath spent his shafts, and ceases now
To bellow through the vast and boundless Deep.
Let us not slip th' occasion, whether scorn,
Or satiate fury yield it from our Foe.
Seest thou yon dreary Plain, forlorn and wilde,
The seat of desolation, voyd of light,
Save what the glimmering of these livid flames
Casts pale and dreadful? Thither let us tend
From off the tossing of these fiery waves,
There rest, if any rest can harbour there,
And reassembling our afflicted Powers,
Consult how we may henceforth most offend
Our Enemy, our own loss how repair,
How overcome this dire Calamity,
What reinforcement we may gain from Hope,
If not what resolution from despare.

Thus Satan talking to his neerest Mate
With Head up-lift above the wave, and Eyes
That sparkling blaz'd, his other Parts besides
Prone on the Flood, extended long and large
Lay floating many a rood, in bulk as huge
As whom the Fables name of monstrous size,
TITANIAN, or EARTH-BORN, that warr'd on JOVE,
BRIARIOS or TYPHON, whom the Den
By ancient TARSUS held, or that Sea-beast
LEVIATHAN, which God of all his works
Created hugest that swim th' Ocean stream:
Him haply slumbring on the NORWAY foam
The Pilot of some small night-founder'd Skiff,
Deeming some Island, oft, as Sea-men tell,
With fixed Anchor in his skaly rind
Moors by his side under the Lee, while Night
Invests the Sea, and wished Morn delayes:
So stretcht out huge in length the Arch-fiend lay
Chain'd on the burning Lake, nor ever thence
Had ris'n or heav'd his head, but that the will
And high permission of all-ruling Heaven
Left him at large to his own dark designs,
That with reiterated crimes he might
Heap on himself damnation, while he sought
Evil to others, and enrag'd might see
How all his malice serv'd but to bring forth
Infinite goodness, grace and mercy shewn
On Man by him seduc't, but on himself
Treble confusion, wrath and vengeance pour'd.
Forthwith upright he rears from off the Pool
His mighty Stature; on each hand the flames
Drivn backward slope their pointing spires, & rowld
In billows, leave i'th' midst a horrid Vale.
Then with expanded wings he stears his flight
Aloft, incumbent on the dusky Air
That felt unusual weight, till on dry Land
He lights, if it were Land that ever burn'd
With solid, as the Lake with liquid fire;
And such appear'd in hue, as when the force
Of subterranean wind transports a Hill
Torn from PELORUS, or the shatter'd side
Of thundring AETNA, whose combustible
And fewel'd entrals thence conceiving Fire,
Sublim'd with Mineral fury, aid the Winds,
And leave a singed bottom all involv'd
With stench and smoak: Such resting found the sole
Of unblest feet. Him followed his next Mate,
Both glorying to have scap't the STYGIAN flood
As Gods, and by their own recover'd strength,
Not by the sufferance of supernal Power.

Is this the Region, this the Soil, the Clime,
Said then the lost Arch Angel, this the seat
That we must change for Heav'n, this mournful gloom
For that celestial light? Be it so, since hee
Who now is Sovran can dispose and bid
What shall be right: fardest from him is best
Whom reason hath equald, force hath made supream
Above his equals. Farewel happy Fields
Where Joy for ever dwells: Hail horrours, hail
Infernal world, and thou profoundest Hell
Receive thy new Possessor: One who brings
A mind not to be chang'd by Place or Time.
The mind is its own place, and in it self
Can make a Heav'n of Hell, a Hell of Heav'n.
What matter where, if I be still the same,
And what I should be, all but less then hee
Whom Thunder hath made greater? Here at least
We shall be free; th' Almighty hath not built
Here for his envy, will not drive us hence:
Here we may reign secure, and in my choyce
To reign is worth ambition though in Hell:
Better to reign in Hell, then serve in Heav'n.
But wherefore let we then our faithful friends,
Th' associates and copartners of our loss
Lye thus astonisht on th' oblivious Pool,
And call them not to share with us their part
In this unhappy Mansion, or once more
With rallied Arms to try what may be yet
Regaind in Heav'n, or what more lost in Hell?

So SATAN spake, and him BEELZEBUB
Thus answer'd. Leader of those Armies bright,
Which but th' Omnipotent none could have foyld,
If once they hear that voyce, their liveliest pledge
Of hope in fears and dangers, heard so oft
In worst extreams, and on the perilous edge
Of battel when it rag'd, in all assaults
Their surest signal, they will soon resume
New courage and revive, though now they lye
Groveling and prostrate on yon Lake of Fire,
As we erewhile, astounded and amaz'd,
No wonder, fall'n such a pernicious highth.

He scarce had ceas't when the superiour Fiend
Was moving toward the shore; his ponderous shield
Ethereal temper, massy, large and round,
Behind him cast; the broad circumference
Hung on his shoulders like the Moon, whose Orb
Through Optic Glass the TUSCAN Artist views
At Ev'ning from the top of FESOLE,
Or in VALDARNO, to descry new Lands,
Rivers or Mountains in her spotty Globe.
His Spear, to equal which the tallest Pine
Hewn on NORWEGIAN hills, to be the Mast
Of some great Ammiral, were but a wand,
He walkt with to support uneasie steps
Over the burning Marle, not like those steps
On Heavens Azure, and the torrid Clime
Smote on him sore besides, vaulted with Fire;
Nathless he so endur'd, till on the Beach
Of that inflamed Sea, he stood and call'd
His Legions, Angel Forms, who lay intrans't
Thick as Autumnal Leaves that strow the Brooks
In VALLOMBROSA, where th' ETRURIAN shades
High overarch't imbowr; or scatterd sedge
Afloat, when with fierce Winds ORION arm'd
Hath vext the Red-Sea Coast, whose waves orethrew
BUSIRIS and his MEMPHIAN Chivalrie,
VVhile with perfidious hatred they pursu'd
The Sojourners of GOSHEN, who beheld
From the safe shore their floating Carkases
And broken Chariot Wheels, so thick bestrown
Abject and lost lay these, covering the Flood,
Under amazement of their hideous change.
He call'd so loud, that all the hollow Deep
Of Hell resounded. Princes, Potentates,
Warriers, the Flowr of Heav'n, once yours, now lost,
If such astonishment as this can sieze
Eternal spirits; or have ye chos'n this place
After the toyl of Battel to repose
Your wearied vertue, for the ease you find
To slumber here, as in the Vales of Heav'n?
Or in this abject posture have ye sworn
To adore the Conquerour? who now beholds
Cherube and Seraph rowling in the Flood
With scatter'd Arms and Ensigns, till anon
His swift pursuers from Heav'n Gates discern
Th' advantage, and descending tread us down
Thus drooping, or with linked Thunderbolts
Transfix us to the bottom of this Gulfe.
Awake, arise, or be for ever fall'n.

They heard, and were abasht, and up they sprung
Upon the wing, as when men wont to watch
On duty, sleeping found by whom they dread,
Rouse and bestir themselves ere well awake.
Nor did they not perceave the evil plight
In which they were, or the fierce pains not feel;
Yet to their Generals Voyce they soon obeyd
Innumerable. As when the potent Rod
Of AMRAMS Son in EGYPTS evill day
Wav'd round the Coast, up call'd a pitchy cloud
Of LOCUSTS, warping on the Eastern Wind,
That ore the Realm of impious PHAROAH hung
Like Night, and darken'd all the Land of NILE:
So numberless were those bad Angels seen
Hovering on wing under the Cope of Hell
'Twixt upper, nether, and surrounding Fires;
Till, as a signal giv'n, th' uplifted Spear
Of their great Sultan waving to direct
Thir course, in even ballance down they light
On the firm brimstone, and fill all the Plain;
A multitude, like which the populous North
Pour'd never from her frozen loyns, to pass
RHENE or the DANAW, when her barbarous Sons
Came like a Deluge on the South, and spread
Beneath GIBRALTAR to the LYBIAN sands.
Forthwith from every Squadron and each Band
The Heads and Leaders thither hast where stood
Their great Commander; Godlike shapes and forms
Excelling human, Princely Dignities,
And Powers that earst in Heaven sat on Thrones;
Though of their Names in heav'nly Records now
Be no memorial, blotted out and ras'd
By thir Rebellion, from the Books of Life.
Nor had they yet among the Sons of EVE
Got them new Names, till wandring ore the Earth,
Through Gods high sufferance for the tryal of man,
By falsities and lyes the greatest part
Of Mankind they corrupted to forsake
God their Creator, and th' invisible
Glory of him, that made them, to transform
Oft to the Image of a Brute, adorn'd
With gay Religions full of Pomp and Gold,
And Devils to adore for Deities:
Then were they known to men by various Names,
And various Idols through the Heathen World.
Say, Muse, their Names then known, who first, who last,
Rous'd from the slumber, on that fiery Couch,
At thir great Emperors call, as next in worth
Came singly where he stood on the bare strand,
While the promiscuous croud stood yet aloof?
The chief were those who from the Pit of Hell
Roaming to seek their prey on earth, durst fix
Their Seats long after next the Seat of God,
Their Altars by his Altar, Gods ador'd
Among the Nations round, and durst abide
JEHOVAH thundring out of SION, thron'd
Between the Cherubim; yea, often plac'd
Within his Sanctuary it self their Shrines,
Abominations; and with cursed things
His holy Rites, and solemn Feasts profan'd,
And with their darkness durst affront his light.
First MOLOCH, horrid King besmear'd with blood
Of human sacrifice, and parents tears,
Though for the noyse of Drums and Timbrels loud
Their childrens cries unheard, that past through fire
To his grim Idol. Him the AMMONITE
Worshipt in RABBA and her watry Plain,
In ARGOB and in BASAN, to the stream
Of utmost ARNON. Nor content with such
Audacious neighbourhood, the wisest heart
Of SOLOMON he led by fraud to build
His Temple right against the Temple of God
On that opprobrious Hill, and made his Grove
The pleasant Vally of HINNOM, TOPHET thence
And black GEHENNA call'd, the Type of Hell.
Next CHEMOS, th' obscene dread of MOABS Sons,
From AROER to NEBO, and the wild
Of Southmost ABARIM; in HESEBON
And HERONAIM, SEONS Realm, beyond
The flowry Dale of SIBMA clad with Vines,
And ELEALE to th' ASPHALTICK Pool.
PEOR his other Name, when he entic'd
ISRAEL in SITTIM on their march from NILE
To do him wanton rites, which cost them woe.
Yet thence his lustful Orgies he enlarg'd
Even to that Hill of scandal, by the Grove
Of MOLOCH homicide, lust hard by hate;
Till good JOSIAH drove them thence to Hell.
With these came they, who from the bordring flood
Of old EUPHRATES to the Brook that parts
EGYPT from SYRIAN ground, had general Names
Of BAALIM and ASHTAROTH, those male,
These Feminine. For Spirits when they please
Can either Sex assume, or both; so soft
And uncompounded is their Essence pure,
Not ti'd or manacl'd with joynt or limb,
Nor founded on the brittle strength of bones,
Like cumbrous flesh; but in what shape they choose
Dilated or condens't, bright or obscure,
Can execute their aerie purposes,
And works of love or enmity fulfill.
For those the Race of ISRAEL oft forsook
Their living strength, and unfrequented left
His righteous Altar, bowing lowly down
To bestial Gods; for which their heads as low
Bow'd down in Battel, sunk before the Spear
Of despicable foes. With these in troop
Came ASTORETH, whom the PHOENICIANS call'd
ASTARTE, Queen of Heav'n, with crescent Horns;
To whose bright Image nightly by the Moon
SIDONIAN Virgins paid their Vows and Songs,
In SION also not unsung, where stood
Her Temple on th' offensive Mountain, built
By that uxorious King, whose heart though large,
Beguil'd by fair Idolatresses, fell
To Idols foul. THAMMUZ came next behind,
Whose annual wound in LEBANON allur'd
The SYRIAN Damsels to lament his fate
In amorous dittyes all a Summers day,
While smooth ADONIS from his native Rock
Ran purple to the Sea, suppos'd with blood
Of THAMMUZ yearly wounded: the Love-tale
Infected SIONS daughters with like heat,
Whose wanton passions in the sacred Porch
EZEKIEL saw, when by the Vision led
His eye survay'd the dark Idolatries
Of alienated JUDAH. Next came one
Who mourn'd in earnest, when the Captive Ark
Maim'd his brute Image, head and hands lopt off
In his own Temple, on the grunsel edge,
Where he fell flat, and sham'd his Worshipers:
DAGON his Name, Sea Monster, upward Man
And downward Fish: yet had his Temple high
Rear'd in AZOTUS, dreaded through the Coast
Of PALESTINE, in GATH and ASCALON,
And ACCARON and GAZA's frontier bounds.
Him follow'd RIMMON, whose delightful Seat
Was fair DAMASCUS, on the fertil Banks
Of ABBANA and PHARPHAR, lucid streams.
He also against the house of God was bold:
A Leper once he lost and gain'd a King,
AHAZ his sottish Conquerour, whom he drew
Gods Altar to disparage and displace
For one of SYRIAN mode, whereon to burn
His odious offrings, and adore the Gods
Whom he had vanquisht. After these appear'd
A crew who under Names of old Renown,
OSIRIS, ISIS, ORUS and their Train
With monstrous shapes and sorceries abus'd
Fanatic EGYPT and her Priests, to seek
Thir wandring Gods disguis'd in brutish forms
Rather then human. Nor did ISRAEL scape
Th' infection when their borrow'd Gold compos'd
The Calf in OREB: and the Rebel King
Doubl'd that sin in BETHEL and in DAN,
Lik'ning his Maker to the Grazed Ox,
JEHOVAH, who in one Night when he pass'd
From EGYPT marching, equal'd with one stroke
Both her first born and all her bleating Gods.
BELIAL came last, then whom a Spirit more lewd
Fell not from Heaven, or more gross to love
Vice for it self: To him no Temple stood
Or Altar smoak'd; yet who more oft then hee
In Temples and at Altars, when the Priest
Turns Atheist, as did ELY'S Sons, who fill'd
With lust and violence the house of God.
In Courts and Palaces he also Reigns
And in luxurious Cities, where the noyse
Of riot ascends above thir loftiest Towrs,
And injury and outrage: And when Night
Darkens the Streets, then wander forth the Sons
Of BELIAL, flown with insolence and wine.
Witness the Streets of SODOM, and that night
In GIBEAH, when hospitable Dores
Yielded thir Matrons to prevent worse rape.
These were the prime in order and in might;
The rest were long to tell, though far renown'd,
Th' IONIAN Gods, of JAVANS Issue held
Gods, yet confest later then Heav'n and Earth
Thir boasted Parents; TITAN Heav'ns first born
With his enormous brood, and birthright seis'd
By younger SATURN, he from mightier JOVE
His own and RHEA'S Son like measure found;
So JOVE usurping reign'd: these first in CREET
And IDA known, thence on the Snowy top
Of cold OLYMPUS rul'd the middle Air
Thir highest Heav'n; or on the DELPHIAN Cliff,
Or in DODONA, and through all the bounds
Of DORIC Land; or who with SATURN old
Fled over ADRIA to th' HESPERIAN Fields,
And ore the CELTIC roam'd the utmost Isles.
All these and more came flocking; but with looks
Down cast and damp, yet such wherein appear'd
Obscure som glimps of joy, to have found thir chief
Not in despair, to have found themselves not lost
In loss it self; which on his count'nance cast
Like doubtful hue: but he his wonted pride
Soon recollecting, with high words, that bore
Semblance of worth not substance, gently rais'd
Their fainted courage, and dispel'd their fears.
Then strait commands that at the warlike sound
Of Trumpets loud and Clarions be upreard
His mighty Standard; that proud honour claim'd
AZAZEL as his right, a Cherube tall:
Who forthwith from the glittering Staff unfurld
Th' Imperial Ensign, which full high advanc't
Shon like a Meteor streaming to the Wind
With Gemms and Golden lustre rich imblaz'd,
Seraphic arms and Trophies: all the while
Sonorous mettal blowing Martial sounds:
At which the universal Host upsent
A shout that tore Hells Concave, and beyond
Frighted the Reign of CHAOS and old Night.
All in a moment through the gloom were seen
Ten thousand Banners rise into the Air
With Orient Colours waving: with them rose
A Forrest huge of Spears: and thronging Helms
Appear'd, and serried Shields in thick array
Of depth immeasurable: Anon they move
In perfect PHALANX to the Dorian mood
Of Flutes and soft Recorders; such as rais'd
To highth of noblest temper Hero's old
Arming to Battel, and in stead of rage
Deliberate valour breath'd, firm and unmov'd
With dread of death to flight or foul retreat,
Nor wanting power to mitigate and swage
With solemn touches, troubl'd thoughts, and chase
Anguish and doubt and fear and sorrow and pain
From mortal or immortal minds. Thus they
Breathing united force with fixed thought
Mov'd on in silence to soft Pipes that charm'd
Thir painful steps o're the burnt soyle; and now
Advanc't in view they stand, a horrid Front
Of dreadful length and dazling Arms, in guise
Of Warriers old with order'd Spear and Shield,
Awaiting what command thir mighty Chief
Had to impose: He through the armed Files
Darts his experienc't eye, and soon traverse
The whole Battalion views, thir order due,
Thir visages and stature as of Gods,
Thir number last he summs. And now his heart
Distends with pride, and hardning in his strength
Glories: For never since created man,
Met such imbodied force, as nam'd with these
Could merit more then that small infantry
Warr'd on by Cranes: though all the Giant brood
Of PHLEGRA with th' Heroic Race were joyn'd
That fought at THEB'S and ILIUM, on each side
Mixt with auxiliar Gods; and what resounds
In Fable or ROMANCE of UTHERS Son
Begirt with BRITISH and ARMORIC Knights;
And all who since, Baptiz'd or Infidel
Jousted in ASPRAMONT or MONTALBAN,
DAMASCO, or MAROCCO, or TREBISOND,
Or whom BISERTA sent from AFRIC shore
When CHARLEMAIN with all his Peerage fell
By FONTARABBIA. Thus far these beyond
Compare of mortal prowess, yet observ'd
Thir dread Commander: he above the rest
In shape and gesture proudly eminent
Stood like a Towr; his form had yet not lost
All her Original brightness, nor appear'd
Less then Arch Angel ruind, and th' excess
Of Glory obscur'd: As when the Sun new ris'n
Looks through the Horizontal misty Air
Shorn of his Beams, or from behind the Moon
In dim Eclips disastrous twilight sheds
On half the Nations, and with fear of change
Perplexes Monarchs. Dark'n'd so, yet shon
Above them all th' Arch Angel: but his face
Deep scars of Thunder had intrencht, and care
Sat on his faded cheek, but under Browes
Of dauntless courage, and considerate Pride
Waiting revenge: cruel his eye, but cast
Signs of remorse and passion to behold
The fellows of his crime, the followers rather
(Far other once beheld in bliss) condemn'd
For ever now to have their lot in pain,
Millions of Spirits for his fault amerc't
Of Heav'n, and from Eternal Splendors flung
For his revolt, yet faithfull how they stood,
Thir Glory witherd. As when Heavens Fire
Hath scath'd the Forrest Oaks, or Mountain Pines,
With singed top their stately growth though bare
Stands on the blasted Heath. He now prepar'd
To speak; whereat their doubl'd Ranks they bend
From Wing to Wing, and half enclose him round
With all his Peers: attention held them mute.
Thrice he assayd, and thrice in spite of scorn,
Tears such as Angels weep, burst forth: at last
Words interwove with sighs found out their way.

O Myriads of immortal Spirits, O Powers
Matchless, but with th' Almighty, and that strife
Was not inglorious, though th' event was dire,
As this place testifies, and this dire change
Hateful to utter: but what power of mind
Foreseeing or presaging, from the Depth
Of knowledge past or present, could have fear'd,
How such united force of Gods, how such
As stood like these, could ever know repulse?
For who can yet beleeve, though after loss,
That all these puissant Legions, whose exile
Hath emptied Heav'n, shall faile to re-ascend
Self-rais'd, and repossess their native seat.
For me, be witness all the Host of Heav'n,
If counsels different, or danger shun'd
By me, have lost our hopes. But he who reigns
Monarch in Heav'n, till then as one secure
Sat on his Throne, upheld by old repute,
Consent or custome, and his Regal State
Put forth at full, but still his strength conceal'd,
Which tempted our attempt, and wrought our fall.
Henceforth his might we know, and know our own
So as not either to provoke, or dread
New warr, provok't; our better part remains
To work in close design, by fraud or guile
What force effected not: that he no less
At length from us may find, who overcomes
By force, hath overcome but half his foe.
Space may produce new Worlds; whereof so rife
There went a fame in Heav'n that he ere long
Intended to create, and therein plant
A generation, whom his choice regard
Should favour equal to the Sons of Heaven:
Thither, if but to prie, shall be perhaps
Our first eruption, thither or elsewhere:
For this Infernal Pit shall never hold
Caelestial Spirits in Bondage, nor th' Abysse
Long under darkness cover. But these thoughts
Full Counsel must mature: Peace is despaird,
For who can think Submission? Warr then, Warr
Open or understood must be resolv'd.

He spake: and to confirm his words, out-flew
Millions of flaming swords, drawn from the thighs
Of mighty Cherubim; the sudden blaze
Far round illumin'd hell: highly they rag'd
Against the Highest, and fierce with grasped arm's
Clash'd on their sounding shields the din of war,
Hurling defiance toward the vault of Heav'n.

There stood a Hill not far whose griesly top
Belch'd fire and rowling smoak; the rest entire
Shon with a glossie scurff, undoubted sign
That in his womb was hid metallic Ore,
The work of Sulphur. Thither wing'd with speed
A numerous Brigad hasten'd. As when bands
Of Pioners with Spade and Pickaxe arm'd
Forerun the Royal Camp, to trench a Field,
Or cast a Rampart. MAMMON led them on,
MAMMON, the least erected Spirit that fell
From heav'n, for ev'n in heav'n his looks & thoughts
Were always downward bent, admiring more
The riches of Heav'ns pavement, trod'n Gold,
Then aught divine or holy else enjoy'd
In vision beatific: by him first
Men also, and by his suggestion taught,
Ransack'd the Center, and with impious hands
Rifl'd the bowels of thir mother Earth
For Treasures better hid. Soon had his crew
Op'nd into the Hill a spacious wound
And dig'd out ribs of Gold. Let none admire
That riches grow in Hell; that soyle may best
Deserve the pretious bane. And here let those
Who boast in mortal things, and wondring tell
Of BABEL, and the works of MEMPHIAN Kings,
Learn how thir greatest Monuments of Fame,
And Strength and Art are easily outdone
By Spirits reprobate, and in an hour
What in an age they with incessant toyle
And hands innumerable scarce perform
Nigh on the Plain in many cells prepar'd,
That underneath had veins of liquid fire
Sluc'd from the Lake, a second multitude
With wondrous Art founded the massie Ore,
Severing each kinde, and scum'd the Bullion dross:
A third as soon had form'd within the ground
A various mould, and from the boyling cells
By strange conveyance fill'd each hollow nook,
As in an Organ from one blast of wind
To many a row of Pipes the sound-board breaths.
Anon out of the earth a Fabrick huge
Rose like an Exhalation, with the sound
Of Dulcet Symphonies and voices sweet,
Built like a Temple, where PILASTERS round
Were set, and Doric pillars overlaid
With Golden Architrave; nor did there want
Cornice or Freeze, with bossy Sculptures grav'n,
The Roof was fretted Gold. Not BABILON,
Nor great ALCAIRO such magnificence
Equal'd in all thir glories, to inshrine
BELUS or SERAPIS thir Gods, or seat
Thir Kings, when AEGYPT with ASSYRIA strove
In wealth and luxurie. Th' ascending pile
Stood fixt her stately highth, and strait the dores
Op'ning thir brazen foulds discover wide
Within, her ample spaces, o're the smooth
And level pavement: from the arched roof
Pendant by suttle Magic many a row
Of Starry Lamps and blazing Cressets fed
With Naphtha and ASPHALTUS yeilded light
As from a sky. The hasty multitude
Admiring enter'd, and the work some praise
And some the Architect: his hand was known
In Heav'n by many a Towred structure high,
Where Scepter'd Angels held thir residence,
And sat as Princes, whom the supreme King
Exalted to such power, and gave to rule,
Each in his Herarchie, the Orders bright.
Nor was his name unheard or unador'd
In ancient Greece; and in AUSONIAN land
Men call'd him MULCIBER; and how he fell
From Heav'n, they fabl'd, thrown by angry JOVE
Sheer o're the Chrystal Battlements: from Morn
To Noon he fell, from Noon to dewy Eve,
A Summers day; and with the setting Sun
Dropt from the Zenith like a falling Star,
On LEMNOS th' AEGAEAN Ile: thus they relate,
Erring; for he with this rebellious rout
Fell long before; nor aught avail'd him now
To have built in Heav'n high Towrs; nor did he scape
By all his Engins, but was headlong sent
With his industrious crew to build in hell.
Mean while the winged Haralds by command
Of Sovran power, with awful Ceremony
And Trumpets sound throughout the Host proclaim
A solemn Councel forthwith to be held
At PANDAEMONIUM, the high Capital
Of Satan and his Peers: thir summons call'd
From every and Band squared Regiment
By place or choice the worthiest; they anon
With hundreds and with thousands trooping came
Attended: all access was throng'd, the Gates
And Porches wide, but chief the spacious Hall
(Though like a cover'd field, where Champions bold
Wont ride in arm'd, and at the Soldans chair
Defi'd the best of Panim chivalry
To mortal combat or carreer with Lance)
Thick swarm'd, both on the ground and in the air,
Brusht with the hiss of russling wings. As Bees
In spring time, when the Sun with Taurus rides,
Poure forth thir populous youth about the Hive
In clusters; they among fresh dews and flowers
Flie to and fro, or on the smoothed Plank,
The suburb of thir Straw-built Cittadel,
New rub'd with Baume, expatiate and confer
Thir State affairs. So thick the aerie crowd
Swarm'd and were straitn'd; till the Signal giv'n,
Behold a wonder! they but now who seemd
In bigness to surpass Earths Giant Sons
Now less then smallest Dwarfs, in narrow room
Throng numberless, like that Pigmean Race
Beyond the INDIAN Mount, or Faerie Elves,
Whose midnight Revels, by a Forrest side
Or Fountain fome belated Peasant sees,
Or dreams he sees, while over head the Moon
Sits Arbitress, and neerer to the Earth
Wheels her pale course, they on thir mirth & dance
Intent, with jocond Music charm his ear;
At once with joy and fear his heart rebounds.
Thus incorporeal Spirits to smallest forms
Reduc'd thir shapes immense, and were at large,
Though without number still amidst the Hall
Of that infernal Court. But far within
And in thir own dimensions like themselves
The great Seraphic Lords and Cherubim
In close recess and secret conclave sat
A thousand Demy-Gods on golden seat's,
Frequent and full. After short silence then
And summons read, the great consult began.



Book 2


High on a Throne of Royal State, which far
Outshon the wealth of ORMUS and of IND,
Or where the gorgeous East with richest hand
Showrs on her Kings BARBARIC Pearl & Gold,
Satan exalted sat, by merit rais'd
To that bad eminence; and from despair
Thus high uplifted beyond hope, aspires
Beyond thus high, insatiate to pursue
Vain Warr with Heav'n, and by success untaught
His proud imaginations thus displaid.

Powers and Dominions, Deities of Heav'n,
For since no deep within her gulf can hold
Immortal vigor, though opprest and fall'n,
I give not Heav'n for lost. From this descent
Celestial vertues rising, will appear
More glorious and more dread then from no fall,
And trust themselves to fear no second fate:
Mee though just right, and the fixt Laws of Heav'n
Did first create your Leader, next, free choice,
With what besides, in Counsel or in Fight,
Hath bin achievd of merit, yet this loss
Thus farr at least recover'd, hath much more
Establisht in a safe unenvied Throne
Yeilded with full consent. The happier state
In Heav'n, which follows dignity, might draw
Envy from each inferior; but who here
Will envy whom the highest place exposes
Formost to stand against the Thunderers aime
Your bulwark, and condemns to greatest share
Of endless pain? where there is then no good
For which to strive, no strife can grow up there
From Faction; for none sure will claim in hell
Precedence, none, whose portion is so small
Of present pain, that with ambitious mind
Will covet more. With this advantage then
To union, and firm Faith, and firm accord,
More then can be in Heav'n, we now return
To claim our just inheritance of old,
Surer to prosper then prosperity
Could have assur'd us; and by what best way,
Whether of open Warr or covert guile,
We now debate; who can advise, may speak.

He ceas'd, and next him MOLOC, Scepter'd King
Stood up, the strongest and the fiercest Spirit
That fought in Heav'n; now fiercer by despair:
His trust was with th' Eternal to be deem'd
Equal in strength, and rather then be less
Car'd not to be at all; with that care lost
Went all his fear: of God, or Hell, or worse
He reckd not, and these words thereafter spake.

My sentence is for open Warr: Of Wiles,
More unexpert, I boast not: them let those
Contrive who need, or when they need, not now.
For while they sit contriving, shall the rest,
Millions that stand in Arms, and longing wait
The Signal to ascend, sit lingring here
Heav'ns fugitives, and for thir dwelling place
Accept this dark opprobrious Den of shame,
The Prison of his Tyranny who Reigns
By our delay? no, let us rather choose
Arm'd with Hell flames and fury all at once
O're Heav'ns high Towrs to force resistless way,
Turning our Tortures into horrid Arms
Against the Torturer; when to meet the noise
Of his Almighty Engin he shall hear
Infernal Thunder, and for Lightning see
Black fire and horror shot with equal rage
Among his Angels; and his Throne it self
Mixt with TARTAREAN Sulphur, and strange fire,
His own invented Torments. But perhaps
The way seems difficult and steep to scale
With upright wing against a higher foe.
Let such bethink them, if the sleepy drench
Of that forgetful Lake benumme not still,
That in our proper motion we ascend
Up to our native seat: descent and fall
To us is adverse. Who but felt of late
When the fierce Foe hung on our brok'n Rear
Insulting, and pursu'd us through the Deep,
With what compulsion and laborious flight
We sunk thus low? Th' ascent is easie then;
Th' event is fear'd; should we again provoke
Our stronger, some worse way his wrath may find
To our destruction: if there be in Hell
Fear to be worse destroy'd: what can be worse
Then to dwell here, driv'n out from bliss, condemn'd
In this abhorred deep to utter woe;
Where pain of unextinguishable fire
Must exercise us without hope of end
The Vassals of his anger, when the Scourge
Inexorably, and the torturing houre
Calls us to Penance? More destroy'd then thus
We should be quite abolisht and expire.
What fear we then? what doubt we to incense
His utmost ire? which to the highth enrag'd,
Will either quite consume us, and reduce
To nothing this essential, happier farr
Then miserable to have eternal being:
Or if our substance be indeed Divine,
And cannot cease to be, we are at worst
On this side nothing; and by proof we feel
Our power sufficient to disturb his Heav'n,
And with perpetual inrodes to Allarme,
Though inaccessible, his fatal Throne:
Which if not Victory is yet Revenge.

He ended frowning, and his look denounc'd
Desperate revenge, and Battel dangerous
To less then Gods. On th' other side up rose
BELIAL, in act more graceful and humane;
A fairer person lost not Heav'n; he seemd
For dignity compos'd and high exploit:
But all was false and hollow; though his Tongue
Dropt Manna, and could make the worse appear
The better reason, to perplex and dash
Maturest Counsels: for his thoughts were low;
To vice industrious, but to Nobler deeds
Timorous and slothful: yet he pleas'd the eare,
And with perswasive accent thus began.

I should be much for open Warr, O Peers,
As not behind in hate; if what was urg'd
Main reason to perswade immediate Warr,
Did not disswade me most, and seem to cast
Ominous conjecture on the whole success:
When he who most excels in fact of Arms,
In what he counsels and in what excels
Mistrustful, grounds his courage on despair
And utter dissolution, as the scope
Of all his aim, after some dire revenge.
First, what Revenge? the Towrs of Heav'n are fill'd
With Armed watch, that render all access
Impregnable; oft on the bordering Deep
Encamp thir Legions, or with obscure wing
Scout farr and wide into the Realm of night,
Scorning surprize. Or could we break our way
By force, and at our heels all Hell should rise
With blackest Insurrection, to confound
Heav'ns purest Light, yet our great Enemie
All incorruptible would on his Throne
Sit unpolluted, and th' Ethereal mould
Incapable of stain would soon expel
Her mischief, and purge off the baser fire
Victorious. Thus repuls'd, our final hope
Is flat despair: we must exasperate
Th' Almighty Victor to spend all his rage,
And that must end us, that must be our cure,
To be no more; sad cure; for who would loose,
Though full of pain, this intellectual being,
Those thoughts that wander through Eternity,
To perish rather, swallowd up and lost
In the wide womb of uncreated night,
Devoid of sense and motion? and who knows,
Let this be good, whether our angry Foe
Can give it, or will ever? how he can
Is doubtful; that he never will is sure.
Will he, so wise, let loose at once his ire,
Belike through impotence, or unaware,
To give his Enemies thir wish, and end
Them in his anger, whom his anger saves
To punish endless? wherefore cease we then?
Say they who counsel Warr, we are decreed,
Reserv'd and destin'd to Eternal woe;
Whatever doing, what can we suffer more,
What can we suffer worse? is this then worst,
Thus sitting, thus consulting, thus in Arms?
What when we fled amain, pursu'd and strook
With Heav'ns afflicting Thunder, and besought
The Deep to shelter us? this Hell then seem'd
A refuge from those wounds: or when we lay
Chain'd on the burning Lake? that sure was worse.
What if the breath that kindl'd those grim fires
Awak'd should blow them into sevenfold rage
And plunge us in the Flames? or from above
Should intermitted vengeance Arme again
His red right hand to plague us? what if all
Her stores were op'n'd, and this Firmament
Of Hell should spout her Cataracts of Fire,
Impendent horrors, threatning hideous fall
One day upon our heads; while we perhaps
Designing or exhorting glorious Warr,
Caught in a fierie Tempest shall be hurl'd
Each on his rock transfixt, the sport and prey
Of racking whirlwinds, or for ever sunk
Under yon boyling Ocean, wrapt in Chains;
There to converse with everlasting groans,
Unrespited, unpitied, unrepreevd,
Ages of hopeless end; this would be worse.
Warr therefore, open or conceal'd, alike
My voice disswades; for what can force or guile
With him, or who deceive his mind, whose eye
Views all things at one view? he from heav'ns highth
All these our motions vain, sees and derides;
Not more Almighty to resist our might
Then wise to frustrate all our plots and wiles.
Shall we then live thus vile, the race of Heav'n
Thus trampl'd, thus expell'd to suffer here
Chains & these Torments? better these then worse
By my advice; since fate inevitable
Subdues us, and Omnipotent Decree,
The Victors will. To suffer, as to doe,
Our strength is equal, nor the Law unjust
That so ordains: this was at first resolv'd,
If we were wise, against so great a foe
Contending, and so doubtful what might fall.
I laugh, when those who at the Spear are bold
And vent'rous, if that fail them, shrink and fear
What yet they know must follow, to endure
Exile, or ignominy, or bonds, or pain,
The sentence of thir Conquerour: This is now
Our doom; which if we can sustain and bear,
Our Supream Foe in time may much remit
His anger, and perhaps thus farr remov'd
Not mind us not offending, satisfi'd
With what is punish't; whence these raging fires
Will slack'n, if his breath stir not thir flames.
Our purer essence then will overcome
Thir noxious vapour, or enur'd not feel,
Or chang'd at length, and to the place conformd
In temper and in nature, will receive
Familiar the fierce heat, and void of pain;
This horror will grow milde, this darkness light,
Besides what hope the never-ending flight
Of future days may bring, what chance, what change
Worth waiting, since our present lot appeers
For happy though but ill, for ill not worst,
If we procure not to our selves more woe.

Thus BELIAL with words cloath'd in reasons garb
Counsel'd ignoble ease, and peaceful sloath,
Not peace: and after him thus MAMMON spake.

Either to disinthrone the King of Heav'n
We warr, if warr be best, or to regain
Our own right lost: him to unthrone we then
May hope, when everlasting Fate shall yeild
To fickle Chance, and CHAOS judge the strife:
The former vain to hope argues as vain
The latter: for what place can be for us
Within Heav'ns bound, unless Heav'ns Lord supream
We overpower? Suppose he should relent
And publish Grace to all, on promise made
Of new Subjection; with what eyes could we
Stand in his presence humble, and receive
Strict Laws impos'd, to celebrate his Throne
With warbl'd Hymns, and to his Godhead sing
Forc't Halleluiah's; while he Lordly sits
Our envied Sovran, and his Altar breathes
Ambrosial Odours and Ambrosial Flowers,
Our servile offerings. This must be our task
In Heav'n, this our delight; how wearisom
Eternity so spent in worship paid
To whom we hate. Let us not then pursue
By force impossible, by leave obtain'd
Unacceptable, though in Heav'n, our state
Of splendid vassalage, but rather seek
Our own good from our selves, and from our own
Live to our selves, though in this vast recess,
Free, and to none accountable, preferring
Hard liberty before the easie yoke
Of servile Pomp. Our greatness will appear
Then most conspicuous, when great things of small,
Useful of hurtful, prosperous of adverse
We can create, and in what place so e're
Thrive under evil, and work ease out of pain
Through labour and endurance. This deep world
Of darkness do we dread? How oft amidst
Thick clouds and dark doth Heav'ns all-ruling Sire
Choose to reside, his Glory unobscur'd,
And with the Majesty of darkness round
Covers his Throne; from whence deep thunders roar
Must'ring thir rage, and Heav'n resembles Hell?
As he our Darkness, cannot we his Light
Imitate when we please? This Desart soile
Wants not her hidden lustre, Gemms and Gold;
Nor want we skill or art, from whence to raise
Magnificence; and what can Heav'n shew more?
Our torments also may in length of time
Become our Elements, these piercing Fires
As soft as now severe, our temper chang'd
Into their temper; which must needs remove
The sensible of pain. All things invite
To peaceful Counsels, and the settl'd State
Of order, how in safety best we may
Compose our present evils, with regard
Of what we are and where, dismissing quite
All thoughts of Warr: ye have what I advise.

He scarce had finisht, when such murmur filld
Th' Assembly, as when hollow Rocks retain
The sound of blustring winds, which all night long
Had rous'd the Sea, now with hoarse cadence lull
Sea-faring men orewatcht, whose Bark by chance
Or Pinnace anchors in a craggy Bay
After the Tempest: Such applause was heard
As MAMMON ended, and his Sentence pleas'd,
Advising peace: for such another Field
They dreaded worse then Hell: so much the fear
Of Thunder and the Sword of MICHAEL
Wrought still within them; and no less desire
To found this nether Empire, which might rise
By pollicy, and long process of time,
In emulation opposite to Heav'n.
Which when BEELZEBUB perceiv'd, then whom,
SATAN except, none higher sat, with grave
Aspect he rose, and in his rising seem'd
A Pillar of State; deep on his Front engraven
Deliberation sat and publick care;
And Princely counsel in his face yet shon,
Majestick though in ruin: sage he stood
With ATLANTEAN shoulders fit to bear
The weight of mightiest Monarchies; his look
Drew audience and attention still as Night
Or Summers Noon-tide air, while thus he spake.

Thrones and imperial Powers, off-spring of heav'n,
Ethereal Vertues; or these Titles now
Must we renounce, and changing stile be call'd
Princes of Hell? for so the popular vote
Inclines, here to continue, and build up here
A growing Empire; doubtless; while we dream,
And know not that the King of Heav'n hath doom'd
This place our dungeon, not our safe retreat
Beyond his Potent arm, to live exempt
From Heav'ns high jurisdiction, in new League
Banded against his Throne, but to remaine
In strictest bondage, though thus far remov'd,
Under th' inevitable curb, reserv'd
His captive multitude: For he, be sure,
In highth or depth, still first and last will Reign
Sole King, and of his Kingdom loose no part
By our revolt, but over Hell extend
His Empire, and with Iron Scepter rule
Us here, as with his Golden those in Heav'n.
What sit we then projecting Peace and Warr?
Warr hath determin'd us, and foild with loss
Irreparable; tearms of peace yet none
Voutsaf't or sought; for what peace will be giv'n
To us enslav'd, but custody severe,
And stripes, and arbitrary punishment
Inflicted? and what peace can we return,
But to our power hostility and hate,
Untam'd reluctance, and revenge though slow,
Yet ever plotting how the Conquerour least
May reap his conquest, and may least rejoyce
In doing what we most in suffering feel?
Nor will occasion want, nor shall we need
With dangerous expedition to invade
Heav'n, whose high walls fear no assault or Siege,
Or ambush from the Deep. What if we find
Some easier enterprize? There is a place
(If ancient and prophetic fame in Heav'n
Err not) another World, the happy seat
Of som new Race call'd MAN, about this time
To be created like to us, though less
In power and excellence, but favour'd more
Of him who rules above; so was his will
Pronounc'd among the Gods, and by an Oath,
That shook Heav'ns whol circumference, confirm'd.
Thither let us bend all our thoughts, to learn
What creatures there inhabit, of what mould,
Or substance, how endu'd, and what thir Power,
And where thir weakness, how attempted best,
By force or suttlety: Though Heav'n be shut,
And Heav'ns high Arbitrator sit secure
In his own strength, this place may lye expos'd
The utmost border of his Kingdom, left
To their defence who hold it: here perhaps
Som advantagious act may be achiev'd
By sudden onset, either with Hell fire
To waste his whole Creation, or possess
All as our own, and drive as we were driven,
The punie habitants, or if not drive,
Seduce them to our Party, that thir God
May prove thir foe, and with repenting hand
Abolish his own works. This would surpass
Common revenge, and interrupt his joy
In our Confusion, and our Joy upraise
In his disturbance; when his darling Sons
Hurl'd headlong to partake with us, shall curse
Thir frail Originals, and faded bliss,
Faded so soon. Advise if this be worth
Attempting, or to sit in darkness here
Hatching vain Empires. Thus BEELZEBUB
Pleaded his devilish Counsel, first devis'd
By SATAN, and in part propos'd: for whence,
But from the Author of all ill could Spring
So deep a malice, to confound the race
Of mankind in one root, and Earth with Hell
To mingle and involve, done all to spite
The great Creatour? But thir spite still serves
His glory to augment. The bold design
Pleas'd highly those infernal States, and joy
Sparkl'd in all thir eyes; with full assent
They vote: whereat his speech he thus renews.

Well have ye judg'd, well ended long debate,
Synod of Gods, and like to what ye are,
Great things resolv'd; which from the lowest deep
Will once more lift us up, in spight of Fate,
Neerer our ancient Seat; perhaps in view
Of those bright confines, whence with neighbouring Arms
And opportune excursion we may chance
Re-enter Heav'n; or else in some milde Zone
Dwell not unvisited of Heav'ns fair Light
Secure, and at the brightning Orient beam
Purge off this gloom; the soft delicious Air,
To heal the scarr of these corrosive Fires
Shall breath her balme. But first whom shall we send
In search of this new world, whom shall we find
Sufficient? who shall tempt with wandring feet
The dark unbottom'd infinite Abyss
And through the palpable obscure find out
His uncouth way, or spread his aerie flight
Upborn with indefatigable wings
Over the vast abrupt, ere he arrive
The happy Ile; what strength, what art can then
Suffice, or what evasion bear him safe
Through the strict Senteries and Stations thick
Of Angels watching round? Here he had need
All circumspection, and we now no less
Choice in our suffrage; for on whom we send,
The weight of all and our last hope relies.

This said, he sat; and expectation held
His look suspence, awaiting who appeer'd
To second, or oppose, or undertake
The perilous attempt: but all sat mute,
Pondering the danger with deep thoughts; & each
In others count'nance red his own dismay
Astonisht: none among the choice and prime
Of those Heav'n-warring Champions could be found
So hardie as to proffer or accept
Alone the dreadful voyage; till at last
SATAN, whom now transcendent glory rais'd
Above his fellows, with Monarchal pride
Conscious of highest worth, unmov'd thus spake.

O Progeny of Heav'n, Empyreal Thrones,
With reason hath deep silence and demurr
Seis'd us, though undismaid: long is the way
And hard, that out of Hell leads up to Light;
Our prison strong, this huge convex of Fire,
Outrageous to devour, immures us round
Ninefold, and gates of burning Adamant
Barr'd over us prohibit all egress.
These past, if any pass, the void profound
Of unessential Night receives him next
Wide gaping, and with utter loss of being
Threatens him, plung'd in that abortive gulf.
If thence he scape into what ever world,
Or unknown Region, what remains him less
Then unknown dangers and as hard escape.
But I should ill become this Throne, O Peers,
And this Imperial Sov'ranty, adorn'd
With splendor, arm'd with power, if aught propos'd
And judg'd of public moment, in the shape
Of difficulty or danger could deterre
Me from attempting. Wherefore do I assume
These Royalties, and not refuse to Reign,
Refusing to accept as great a share
Of hazard as of honour, due alike
To him who Reigns, and so much to him due
Of hazard more, as he above the rest
High honourd sits? Go therfore mighty powers,
Terror of Heav'n, though fall'n; intend at home,
While here shall be our home, what best may ease
The present misery, and render Hell
More tollerable; if there be cure or charm
To respite or deceive, or slack the pain
Of this ill Mansion: intermit no watch
Against a wakeful Foe, while I abroad
Through all the coasts of dark destruction seek
Deliverance for us all: this enterprize
None shall partake with me. Thus saying rose
The Monarch, and prevented all reply,
Prudent, least from his resolution rais'd
Others among the chief might offer now
(Certain to be refus'd) what erst they feard;
And so refus'd might in opinion stand
His rivals, winning cheap the high repute
Which he through hazard huge must earn. But they
Dreaded not more th' adventure then his voice
Forbidding; and at once with him they rose;
Thir rising all at once was as the sound
Of Thunder heard remote. Towards him they bend
With awful reverence prone; and as a God
Extoll him equal to the highest in Heav'n:
Nor fail'd they to express how much they prais'd,
That for the general safety he despis'd
His own: for neither do the Spirits damn'd
Loose all thir vertue; least bad men should boast
Thir specious deeds on earth, which glory excites,
Or close ambition varnisht o're with zeal.
Thus they thir doubtful consultations dark
Ended rejoycing in thir matchless Chief:
As when from mountain tops the dusky clouds
Ascending, while the North wind sleeps, o'respread
Heav'ns chearful face, the lowring Element
Scowls ore the dark'nd lantskip Snow, or showre;
If chance the radiant Sun with farewell sweet
Extend his ev'ning beam, the fields revive,
The birds thir notes renew, and bleating herds
Attest thir joy, that hill and valley rings.
O shame to men! Devil with Devil damn'd
Firm concord holds, men onely disagree
Of Creatures rational, though under hope
Of heavenly Grace: and God proclaiming peace,
Yet live in hatred, enmitie, and strife
Among themselves, and levie cruel warres,
Wasting the Earth, each other to destroy:
As if (which might induce us to accord)
Man had not hellish foes anow besides,
That day and night for his destruction waite.

The STYGIAN Councel thus dissolv'd; and forth
In order came the grand infernal Peers,
Midst came thir mighty Paramount, and seemd
Alone th' Antagonist of Heav'n, nor less
Then Hells dread Emperour with pomp Supream,
And God-like imitated State; him round
A Globe of fierie Seraphim inclos'd
With bright imblazonrie, and horrent Arms.
Then of thir Session ended they bid cry
With Trumpets regal sound the great result:
Toward the four winds four speedy Cherubim
Put to thir mouths the sounding Alchymie
By Haralds voice explain'd: the hollow Abyss
Heard farr and wide, and all the host of Hell
With deafning shout, return'd them loud acclaim.
Thence more at ease thir minds and somwhat rais'd
By false presumptuous hope, the ranged powers
Disband, and wandring, each his several way
Pursues, as inclination or sad choice
Leads him perplext, where he may likeliest find
Truce to his restless thoughts, and entertain
The irksome hours, till his great Chief return.
Part on the Plain, or in the Air sublime
Upon the wing, or in swift race contend,
As at th' Olympian Games or PYTHIAN fields;
Part curb thir fierie Steeds, or shun the Goal
With rapid wheels, or fronted Brigads form.
As when to warn proud Cities warr appears
Wag'd in the troubl'd Skie, and Armies rush
To Battel in the Clouds, before each Van
Pric forth the Aerie Knights, and couch thir spears
Till thickest Legions close; with feats of Arms
From either end of Heav'n the welkin burns.
Others with vast TYPHOEAN rage more fell
Rend up both Rocks and Hills, and ride the Air
In whirlwind; Hell scarce holds the wilde uproar.
As when ALCIDES from OEALIA Crown'd
With conquest, felt th' envenom'd robe, and tore
Through pain up by the roots THESSALIAN Pines,
And LICHAS from the top of OETA threw
Into th' EUBOIC Sea. Others more milde,
Retreated in a silent valley, sing
With notes Angelical to many a Harp
Thir own Heroic deeds and hapless fall
By doom of Battel; and complain that Fate
Free Vertue should enthrall to Force or Chance.
Thir song was partial, but the harmony
(What could it less when Spirits immortal sing?)
Suspended Hell, and took with ravishment
The thronging audience. In discourse more sweet
(For Eloquence the Soul, Song charms the Sense,)
Others apart sat on a Hill retir'd,
In thoughts more elevate, and reason'd high
Of Providence, Foreknowledge, Will, and Fate,
Fixt Fate, free will, foreknowledge absolute,
And found no end, in wandring mazes lost.
Of good and evil much they argu'd then,
Of happiness and final misery,
Passion and Apathie, and glory and shame,
Vain wisdom all, and false Philosophie:
Yet with a pleasing sorcerie could charm
Pain for a while or anguish, and excite
Fallacious hope, or arm th' obdured brest
With stubborn patience as with triple steel.
Another part in Squadrons and gross Bands,
On bold adventure to discover wide
That dismal world, if any Clime perhaps
Might yeild them easier habitation, bend
Four ways thir flying March, along the Banks
Of four infernal Rivers that disgorge
Into the burning Lake thir baleful streams;
Abhorred STYX the flood of deadly hate,
Sad ACHERON of sorrow, black and deep;
COCYTUS, nam'd of lamentation loud
Heard on the ruful stream; fierce PHLEGETON
Whose waves of torrent fire inflame with rage.
Farr off from these a slow and silent stream,
LETHE the River of Oblivion roules
Her watrie Labyrinth, whereof who drinks,
Forthwith his former state and being forgets,
Forgets both joy and grief, pleasure and pain.
Beyond this flood a frozen Continent
Lies dark and wilde, beat with perpetual storms
Of Whirlwind and dire Hail, which on firm land
Thaws not, but gathers heap, and ruin seems
Of ancient pile; all else deep snow and ice,
A gulf profound as that SERBONIAN Bog
Betwixt DAMIATA and mount CASIUS old,
Where Armies whole have sunk: the parching Air
Burns frore, and cold performs th' effect of Fire.
Thither by harpy-footed Furies hail'd,
At certain revolutions all the damn'd
Are brought: and feel by turns the bitter change
Of fierce extreams, extreams by change more fierce,
From Beds of raging Fire to starve in Ice
Thir soft Ethereal warmth, and there to pine
Immovable, infixt, and frozen round,
Periods of time, thence hurried back to fire.
They ferry over this LETHEAN Sound
Both to and fro, thir sorrow to augment,
And wish and struggle, as they pass, to reach
The tempting stream, with one small drop to loose
In sweet forgetfulness all pain and woe,
All in one moment, and so neer the brink;
But fate withstands, and to oppose th' attempt
MEDUSA with GORGONIAN terror guards
The Ford, and of it self the water flies
All taste of living wight, as once it fled
The lip of TANTALUS. Thus roving on
In confus'd march forlorn, th' adventrous Bands
With shuddring horror pale, and eyes agast
View'd first thir lamentable lot, and found
No rest: through many a dark and drearie Vaile
They pass'd, and many a Region dolorous,
O're many a Frozen, many a Fierie Alpe,
Rocks, Caves, Lakes, Fens, Bogs, Dens, and shades of death,
A Universe of death, which God by curse
Created evil, for evil only good,
Where all life dies, death lives, and nature breeds,
Perverse, all monstrous, all prodigious things,
Abominable, inutterable, and worse
Then Fables yet have feign'd, or fear conceiv'd,
GORGONS and HYDRA'S, and CHIMERA'S dire.

Mean while the Adversary of God and Man,
SATAN with thoughts inflam'd of highest design,
Puts on swift wings, and toward the Gates of Hell
Explores his solitary flight; som times
He scours the right hand coast, som times the left,
Now shaves with level wing the Deep, then soares
Up to the fiery concave touring high.
As when farr off at Sea a Fleet descri'd
Hangs in the Clouds, by AEQUINOCTIAL Winds
Close sailing from BENGALA, or the Iles
Of TERNATE and TIDORE, whence Merchants bring
Thir spicie Drugs: they on the trading Flood
Through the wide ETHIOPIAN to the Cape
Ply stemming nightly toward the Pole. So seem'd
Farr off the flying Fiend: at last appeer
Hell bounds high reaching to the horrid Roof,
And thrice threefold the Gates; three folds were Brass
Three Iron, three of Adamantine Rock,
Impenitrable, impal'd with circling fire,
Yet unconsum'd. Before the Gates there sat
On either side a formidable shape;
The one seem'd Woman to the waste, and fair,
But ended foul in many a scaly fould
Voluminous and vast, a Serpent arm'd
With mortal sting: about her middle round
A cry of Hell Hounds never ceasing bark'd
With wide CERBEREAN mouths full loud, and rung
A hideous Peal: yet, when they list, would creep,
If aught disturb'd thir noyse, into her woomb,
And kennel there, yet there still bark'd and howl'd
Within unseen. Farr less abhorrd then these
Vex'd SCYLLA bathing in the Sea that parts
CALABRIA from the hoarce TRINACRIAN shore:
Nor uglier follow the Night-Hag, when call'd
In secret, riding through the Air she comes
Lur'd with the smell of infant blood, to dance
With LAPLAND Witches, while the labouring Moon
Eclipses at thir charms. The other shape,
If shape it might be call'd that shape had none
Distinguishable in member, joynt, or limb,
Or substance might be call'd that shadow seem'd,
For each seem'd either; black it stood as Night,
Fierce as ten Furies, terrible as Hell,
And shook a dreadful Dart; what seem'd his head
The likeness of a Kingly Crown had on.
SATAN was now at hand, and from his seat
The Monster moving onward came as fast,
With horrid strides, Hell trembled as he strode.
Th' undaunted Fiend what this might be admir'd,
Admir'd, not fear'd; God and his Son except,
Created thing naught vallu'd he nor shun'd;
And with disdainful look thus first began.

Whence and what art thou, execrable shape,
That dar'st, though grim and terrible, advance
Thy miscreated Front athwart my way
To yonder Gates? through them I mean to pass,
That be assur'd, without leave askt of thee:
Retire, or taste thy folly, and learn by proof,
Hell-born, not to contend with Spirits of Heav'n.

To whom the Goblin full of wrauth reply'd,
Art thou that Traitor Angel, art thou hee,
Who first broke peace in Heav'n and Faith, till then
Unbrok'n, and in proud rebellious Arms
Drew after him the third part of Heav'ns Sons
Conjur'd against the highest, for which both Thou
And they outcast from God, are here condemn'd
To waste Eternal daies in woe and pain?
And reck'n'st thou thy self with Spirits of Heav'n,
Hell-doomd, and breath'st defiance here and scorn,
Where I reign King, and to enrage thee more,
Thy King and Lord? Back to thy punishment,
False fugitive, and to thy speed add wings,
Least with a whip of Scorpions I pursue
Thy lingring, or with one stroke of this Dart
Strange horror seise thee, and pangs unfelt before.

So spake the grieslie terrour, and in shape,
So speaking and so threatning, grew ten fold
More dreadful and deform: on th' other side
Incenc't with indignation SATAN stood
Unterrifi'd, and like a Comet burn'd,
That fires the length of OPHIUCUS huge
In th' Artick Sky, and from his horrid hair
Shakes Pestilence and Warr. Each at the Head
Level'd his deadly aime; thir fatall hands
No second stroke intend, and such a frown
Each cast at th' other, as when two black Clouds
With Heav'ns Artillery fraught, come rattling on
Over the CASPIAN, then stand front to front
Hov'ring a space, till Winds the signal blow
To joyn thir dark Encounter in mid air:
So frownd the mighty Combatants, that Hell
Grew darker at thir frown, so matcht they stood;
For never but once more was either like
To meet so great a foe: and now great deeds
Had been achiev'd, whereof all Hell had rung,
Had not the Snakie Sorceress that sat
Fast by Hell Gate, and kept the fatal Key,
Ris'n, and with hideous outcry rush'd between.

O Father, what intends thy hand, she cry'd,
Against thy only Son? What fury O Son,
Possesses thee to bend that mortal Dart
Against thy Fathers head? and know'st for whom;
For him who sits above and laughs the while
At thee ordain'd his drudge, to execute
What e're his wrath, which he calls Justice, bids,
His wrath which one day will destroy ye both.

She spake, and at her words the hellish Pest
Forbore, then these to her SATAN return'd:

So strange thy outcry, and thy words so strange
Thou interposest, that my sudden hand
Prevented spares to tell thee yet by deeds
What it intends; till first I know of thee,
What thing thou art, thus double-form'd, and why
In this infernal Vaile first met thou call'st
Me Father, and that Fantasm call'st my Son?
I know thee not, nor ever saw till now
Sight more detestable then him and thee.

T' whom thus the Portress of Hell Gate reply'd;
Hast thou forgot me then, and do I seem
Now in thine eye so foul, once deemd so fair
In Heav'n, when at th' Assembly, and in sight
Of all the Seraphim with thee combin'd
In bold conspiracy against Heav'ns King,
All on a sudden miserable pain
Surpris'd thee, dim thine eyes, and dizzie swumm
In darkness, while thy head flames thick and fast
Threw forth, till on the left side op'ning wide,
Likest to thee in shape and count'nance bright,
Then shining heav'nly fair, a Goddess arm'd
Out of thy head I sprung: amazement seis'd
All th' Host of Heav'n; back they recoild affraid
At first, and call'd me SIN, and for a Sign
Portentous held me; but familiar grown,
I pleas'd, and with attractive graces won
The most averse, thee chiefly, who full oft
Thy self in me thy perfect image viewing
Becam'st enamour'd, and such joy thou took'st
With me in secret, that my womb conceiv'd
A growing burden. Mean while Warr arose,
And fields were fought in Heav'n; wherein remaind
(For what could else) to our Almighty Foe
Cleer Victory, to our part loss and rout
Through all the Empyrean: down they fell
Driv'n headlong from the Pitch of Heaven, down
Into this Deep, and in the general fall
I also; at which time this powerful Key
Into my hand was giv'n, with charge to keep
These Gates for ever shut, which none can pass
Without my op'ning. Pensive here I sat
Alone, but long I sat not, till my womb
Pregnant by thee, and now excessive grown
Prodigious motion felt and rueful throes.
At last this odious offspring whom thou seest
Thine own begotten, breaking violent way
Tore through my entrails, that with fear and pain
Distorted, all my nether shape thus grew
Transform'd: but he my inbred enemie
Forth issu'd, brandishing his fatal Dart
Made to destroy: I fled, and cry'd out DEATH;
Hell trembl'd at the hideous Name, and sigh'd
From all her Caves, and back resounded DEATH.
I fled, but he pursu'd (though more, it seems,
Inflam'd with lust then rage) and swifter far,
Me overtook his mother all dismaid,
And in embraces forcible and foule
Ingendring with me, of that rape begot
These yelling Monsters that with ceasless cry
Surround me, as thou sawst, hourly conceiv'd
And hourly born, with sorrow infinite
To me, for when they list into the womb
That bred them they return, and howle and gnaw
My Bowels, their repast; then bursting forth
Afresh with conscious terrours vex me round,
That rest or intermission none I find.
Before mine eyes in opposition sits
Grim DEATH my Son and foe, who sets them on,
And me his Parent would full soon devour
For want of other prey, but that he knows
His end with mine involvd; and knows that I
Should prove a bitter Morsel, and his bane,
When ever that shall be; so Fate pronounc'd.
But thou O Father, I forewarn thee, shun
His deadly arrow; neither vainly hope
To be invulnerable in those bright Arms,
Though temper'd heav'nly, for that mortal dint,
Save he who reigns above, none can resist.

She finish'd, and the suttle Fiend his lore
Soon learnd, now milder, and thus answerd smooth.
Dear Daughter, since thou claim'st me for thy Sire,
And my fair Son here showst me, the dear pledge
Of dalliance had with thee in Heav'n, and joys
Then sweet, now sad to mention, through dire change
Befalln us unforeseen, unthought of, know
I come no enemie, but to set free
From out this dark and dismal house of pain,
Both him and thee, and all the heav'nly Host
Of Spirits that in our just pretenses arm'd
Fell with us from on high: from them I go
This uncouth errand sole, and one for all
My self expose, with lonely steps to tread
Th' unfounded deep, & through the void immense
To search with wandring quest a place foretold
Should be, and, by concurring signs, ere now
Created vast and round, a place of bliss
In the Pourlieues of Heav'n, and therein plac't
A race of upstart Creatures, to supply
Perhaps our vacant room, though more remov'd,
Least Heav'n surcharg'd with potent multitude
Might hap to move new broiles: Be this or aught
Then this more secret now design'd, I haste
To know, and this once known, shall soon return,
And bring ye to the place where Thou and Death
Shall dwell at ease, and up and down unseen
Wing silently the buxom Air, imbalm'd
With odours; there ye shall be fed and fill'd
Immeasurably, all things shall be your prey.
He ceas'd, for both seemd highly pleasd, and Death
Grinnd horrible a gastly smile, to hear
His famine should be fill'd, and blest his mawe
Destin'd to that good hour: no less rejoyc'd
His mother bad, and thus bespake her Sire.

The key of this infernal Pit by due,
And by command of Heav'ns all-powerful King
I keep, by him forbidden to unlock
These Adamantine Gates; against all force
Death ready stands to interpose his dart,
Fearless to be o'rematcht by living might.
But what ow I to his commands above
Who hates me, and hath hither thrust me down
Into this gloom of TARTARUS profound,
To sit in hateful Office here confin'd,
Inhabitant of Heav'n, and heav'nlie-born,
Here in perpetual agonie and pain,
With terrors and with clamors compasst round
Of mine own brood, that on my bowels feed:
Thou art my Father, thou my Author, thou
My being gav'st me; whom should I obey
But thee, whom follow? thou wilt bring me soon
To that new world of light and bliss, among
The Gods who live at ease, where I shall Reign
At thy right hand voluptuous, as beseems
Thy daughter and thy darling, without end.

Thus saying, from her side the fatal Key,
Sad instrument of all our woe, she took;
And towards the Gate rouling her bestial train,
Forthwith the huge Porcullis high up drew,
Which but her self not all the STYGIAN powers
Could once have mov'd; then in the key-hole turns
Th' intricate wards, and every Bolt and Bar
Of massie Iron or sollid Rock with ease
Unfast'ns: on a sudden op'n flie
With impetuous recoile and jarring sound
Th' infernal dores, and on thir hinges great
Harsh Thunder, that the lowest bottom shook
Of EREBUS. She op'nd, but to shut
Excel'd her power; the Gates wide op'n stood,
That with extended wings a Bannerd Host
Under spread Ensigns marching might pass through
With Horse and Chariots rankt in loose array;
So wide they stood, and like a Furnace mouth
Cast forth redounding smoak and ruddy flame.
Before thir eyes in sudden view appear
The secrets of the hoarie deep, a dark
Illimitable Ocean without bound,
Without dimension, where length, breadth, and highth,
And time and place are lost; where eldest Night
And CHAOS, Ancestors of Nature, hold
Eternal ANARCHIE, amidst the noise
Of endless warrs and by confusion stand.
For hot, cold, moist, and dry, four Champions fierce
Strive here for Maistrie, and to Battel bring
Thir embryon Atoms; they around the flag
Of each his faction, in thir several Clanns,
Light-arm'd or heavy, sharp, smooth, swift or slow,
Swarm populous, unnumber'd as the Sands
Of BARCA or CYRENE'S torrid soil,
Levied to side with warring Winds, and poise
Thir lighter wings. To whom these most adhere,
Hee rules a moment; CHAOS Umpire sits,
And by decision more imbroiles the fray
By which he Reigns: next him high Arbiter
CHANCE governs all. Into this wilde Abyss,
The Womb of nature and perhaps her Grave,
Of neither Sea, nor Shore, nor Air, nor Fire,
But all these in thir pregnant causes mixt
Confus'dly, and which thus must ever fight,
Unless th' Almighty Maker them ordain
His dark materials to create more Worlds,
Into this wilde Abyss the warie fiend
Stood on the brink of Hell and look'd a while,
Pondering his Voyage; for no narrow frith
He had to cross. Nor was his eare less peal'd
With noises loud and ruinous (to compare
Great things with small) then when BELLONA storms,
With all her battering Engines bent to rase
Som Capital City, or less then if this frame
Of Heav'n were falling, and these Elements
In mutinie had from her Axle torn
The stedfast Earth. At last his Sail-broad Vannes
He spreads for flight, and in the surging smoak
Uplifted spurns the ground, thence many a League
As in a cloudy Chair ascending rides
Audacious, but that seat soon failing, meets
A vast vacuitie: all unawares
Fluttring his pennons vain plumb down he drops
Ten thousand fadom deep, and to this hour
Down had been falling, had not by ill chance
The strong rebuff of som tumultuous cloud
Instinct with Fire and Nitre hurried him
As many miles aloft: that furie stay'd,
Quencht in a Boggie SYRTIS, neither Sea,
Nor good dry Land: nigh founderd on he fares,
Treading the crude consistence, half on foot,
Half flying; behoves him now both Oare and Saile.
As when a Gryfon through the Wilderness
With winged course ore Hill or moarie Dale,
Pursues the ARIMASPIAN, who by stelth
Had from his wakeful custody purloind
The guarded Gold: So eagerly the fiend
Ore bog or steep, through strait, rough, dense, or rare,
With head, hands, wings, or feet pursues his way,
And swims or sinks, or wades, or creeps, or flyes:
At length a universal hubbub wilde
Of stunning sounds and voices all confus'd
Born through the hollow dark assaults his eare
With loudest vehemence: thither he plyes,
Undaunted to meet there what ever power
Or Spirit of the nethermost Abyss
Might in that noise reside, of whom to ask
Which way the neerest coast of darkness lyes
Bordering on light; when strait behold the Throne
Of CHAOS, and his dark Pavilion spread
Wide on the wasteful Deep; with him Enthron'd
Sat Sable-vested Night, eldest of things,
The consort of his Reign; and by them stood
ORCUS and ADES, and the dreaded name
Of DEMOGORGON; Rumor next and Chance,
And Tumult and Confusion all imbroild,
And Discord with a thousand various mouths.

T' whom SATAN turning boldly, thus. Ye Powers
And Spirits of this nethermost Abyss,
CHAOS and ANCIENT NIGHT, I come no Spie,
With purpose to explore or to disturb
The secrets of your Realm, but by constraint
Wandring this darksome desart, as my way
Lies through your spacious Empire up to light,
Alone, and without guide, half lost, I seek
What readiest path leads where your gloomie bounds
Confine with Heav'n; or if som other place
From your Dominion won, th' Ethereal King
Possesses lately, thither to arrive
I travel this profound, direct my course;
Directed, no mean recompence it brings
To your behoof, if I that Region lost,
All usurpation thence expell'd, reduce
To her original darkness and your sway
(Which is my present journey) and once more
Erect the Standerd there of ANCIENT NIGHT;
Yours be th' advantage all, mine the revenge.

Thus SATAN; and him thus the Anarch old
With faultring speech and visage incompos'd
Answer'd. I know thee, stranger, who thou art,
That mighty leading Angel, who of late
Made head against Heav'ns King, though overthrown.
I saw and heard, for such a numerous host
Fled not in silence through the frighted deep
With ruin upon ruin, rout on rout,
Confusion worse confounded; and Heav'n Gates
Pourd out by millions her victorious Bands
Pursuing. I upon my Frontieres here
Keep residence; if all I can will serve,
That little which is left so to defend
Encroacht on still through our intestine broiles
Weakning the Scepter of old Night: first Hell
Your dungeon stretching far and wide beneath;
Now lately Heaven and Earth, another World
Hung ore my Realm, link'd in a golden Chain
To that side Heav'n from whence your Legions fell:
If that way be your walk, you have not farr;
So much the neerer danger; goe and speed;
Havock and spoil and ruin are my gain.

He ceas'd; and SATAN staid not to reply,
But glad that now his Sea should find a shore,
With fresh alacritie and force renew'd
Springs upward like a Pyramid of fire
Into the wilde expanse, and through the shock
Of fighting Elements, on all sides round
Environ'd wins his way; harder beset
And more endanger'd, then when ARGO pass'd
Through BOSPORUS betwixt the justling Rocks:
Or when ULYSSES on the Larbord shunnd
CHARYBDIS, and by th' other whirlpool steard.
So he with difficulty and labour hard
Mov'd on, with difficulty and labour hee;
But hee once past, soon after when man fell,
Strange alteration! Sin and Death amain
Following his track, such was the will of Heav'n,
Pav'd after him a broad and beat'n way
Over the dark Abyss, whose boiling Gulf
Tamely endur'd a Bridge of wondrous length
From Hell continu'd reaching th' utmost Orbe
Of this frail World; by which the Spirits perverse
With easie intercourse pass to and fro
To tempt or punish mortals, except whom
God and good Angels guard by special grace.
But now at last the sacred influence
Of light appears, and from the walls of Heav'n
Shoots farr into the bosom of dim Night
A glimmering dawn; here Nature first begins
Her fardest verge, and CHAOS to retire
As from her outmost works a brok'n foe
With tumult less and with less hostile din,
That SATAN with less toil, and now with ease
Wafts on the calmer wave by dubious light
And like a weather-beaten Vessel holds
Gladly the Port, though Shrouds and Tackle torn;
Or in the emptier waste, resembling Air,
Weighs his spread wings, at leasure to behold
Farr off th' Empyreal Heav'n, extended wide
In circuit, undetermind square or round,
With Opal Towrs and Battlements adorn'd
Of living Saphire, once his native Seat;
And fast by hanging in a golden Chain
This pendant world, in bigness as a Starr
Of smallest Magnitude close by the Moon.
Thither full fraught with mischievous revenge,
Accurst, and in a cursed hour he hies.





--------------------------------------------------


[ Usenet FAQs | Search | Web FAQs | Documents | RFC Index ]
comp.graphics.algorithms Frequently Asked Questions

Not finding the answers you need? 
Submit your question for others to see.

There are reader questions on this topic!
Help others by sharing your knowledge

From: orourke@cs.smith.edu (Joseph O'Rourke)
Newsgroups: comp.graphics.algorithms
Subject: comp.graphics.algorithms Frequently Asked Questions
Date: Sat, 15 Feb 2003 16:16:44 +0000 (UTC)
Sender: orourke@grendel.csc.smith.edu
Message-ID: <graphics/algorithms-faq-1-1045325804@cs.smith.edu>
Reply-To: orourke@cs.smith.edu (Joseph O'Rourke)
Keywords: faq computer graphics algorithms geometry
X-Content-Currency: This FAQ changes regularly. See item (0.03) for instructions
   on how to obtain a new copy via FTP.

Posted-By: auto-faq 3.3.1 beta (Perl 5.006)
Archive-name: graphics/algorithms-faq
Posting-Frequency: bi-weekly

Welcome to the FAQ for comp.graphics.algorithms!

Thanks to all who have contributed.  Corrections and contributions
(to orourke@cs.smith.edu) always welcome.  

----------------------------------------------------------------------
This article is Copyright 2003 by Joseph O'Rourke.  It may be freely 
redistributed in its entirety provided that this copyright notice is 
not removed.
----------------------------------------------------------------------

  Changed items this posting (|): 5.04
  New     items this posting (+): none

----------------------------------------------------------------------
History of Changes (approx. last six months):
----------------------------------------------------------------------
Changes in 15 Feb 03 posting:
  5.04: Fixed broken link in clipping article. [Thanks to Keith Forbes.]
Changes in  1 Feb 03 posting:
  0.04: Ashdown Radiosity back in print. [Thanks to Ian Ashdown.]
  0.06: Update BSP FAQ links [Thanks to Ken Shoemake.]
  0.07: Update CGAL links in source article.
  3.11: Broken link re course based on Perlin's Noise book. [Thanks to Mikkel Gjoel.]
  6.01: Add CGAL link to Voronoi source article. [Thanks to Andreas Fabri.]
  7.02: All contributor email addresses removed to protect them from spam.
Changes in 15 Jan 03 posting:
  0.06: Query re reality.sgi.com/bspfaq/ [Thanks to <warp@subphase.de>.]
  0.07: Update moved link on WINGED.ZIP. [Thanks to Ben Landon.]
  0.07: Update Ferrar's ++ 3D rendering library link. [Thanks to F.Iannarilli, Jr.]
  1.06: Added ref to AT&T Graphviz. [Thanks to Michael Meire.]
  2.08: Fix sloan ear-clipping link.  [Thanks to logicalink@juno.com.]
  5.09: Update moved link re caustics. [Thanks to Ben Landon.]
  5.18: Formula for distance between two 3D lines. [Thanks to Daniel Zwick.]
  5.27: New article on transforming normals by Ken Shoemake.
  6.08: Random points on sphere in terms of longitude & latitude [Thanks to Uffe Kousgaard.]
Changes in  1 Jul 02 posting:
  3.14: Correct GIF author info, add URL. [Thanks to Greg Roelofs.]
Changes in  1 May 02 posting:
  0.04: Errata for Watt & Watt book added. [Thanks to Jacob Marner.]
  5.14: 3D viewing revised by Ken Shoemake.
  5.23: Remove (erroneous) 3D medial axis info.
  5.25: New article on quaternions by Ken Shoemake.
  5.26: New article on camera aiming and quaternions by Ken Shoemake.
  6.01: Add (correct) 3D medial axis info.  (Thanks to Tamal Dey.)
  6.09: Plucker coordinates article revised by Ken Shoemake.
Changes in 15 Apr 02 posting:
  3.05: Scaling bitmaps revised by Ken Shoemake.
  3.09: Morphing article written by Ken Shoemake.
  6.08: Added references on random points on a sphere (Ken Shoemake).
Changes in  1 Apr 02 posting:
  1.01: 2D point rotation revised by Ken Shoemake.
  1.01: 2D segment intersection revised by Ken Shoemake.
  5.01: 3D point rotation revised by Ken Shoemake.
  0.07: Greg Ferrar's 3D rendering library no longer available.
Changes in 15 Mar 02 posting:
  2.03: Reference Dan Sunday's winding number algorithm.
  4.04: More detail on Beziers approximating a circle.
        (Thanks to William Gibbons.)
  5.22: Added NASA's "Intersect" code for intersecting triangulated
        surfaces.
  5.23: Updated Cocone software description.
Changes in 15 Feb 02 posting:
  5.03: Noted that Sutherland-Hodgman can clip against any convex polygon.
        (Thanks to Ben Landon.)
  5.15: More links on simplifying meshes. (Thanks to Stefan Krause.)
Changes in  1 Jan 02 posting:
  2.03: Fixed link to Franklin's code. (Thanks to Keith M. Briggs.)
  5.13: Update to SWIFT++; add Terdiman's collision lib.
        (Thanks to Pierre Terdiman.)
Changes in  1 Nov 01 posting:
  6.01,02,03: Update to Qhull 3.1 release (Thanks to Brad Barber.)
Changes in 15 Sep 01 posting:
  0.04: "Radiosity: A Programmer's Perspective" out of print.
  0.05: CQUANT97 link no longer available; RADBIB info updated.
        (Thanks to Ian Ashdown for both.)
  2.01: Explained indices in more efficient formula, and restored
        Sunday's version. (Thanks to Dan Sunday.)
  4.04: Link for approximating a circle via a Bezier curve
        (Thanks to John McDonald, Jr.)
  5.10: Add in link to Jules Bloomenthal's list of papers for algorithms
        that could substitute for the marching cubes algorithm.
  5.11: Refer to 5.10. (Thanks to Eric Haines for both.)
Changes in  1 Sep 01 posting:
  2.01: Fixed indices in efficient area formula 
	(Thanks to peter@Glaze.phys.dal.ca.)
  2.03: Link to classic "Point in Polygon Strategies" article.
        (Thanks to Eric Haines.)
  5.09: Additional references for caustics (Thanks to Lars Brinkhoff.)
  5.11: New links for marching cubes patent (Thanks to John Stone.)
  5.17: Stale link notice.
  5.23: New Cocone link for surface reconstruction.
----------------------------------------------------------------------
Table of Contents
----------------------------------------------------------------------

0. General Information
   0.01: Charter of comp.graphics.algorithms
   0.02: Are the postings to comp.graphics.algorithms archived?
   0.03: How can I get this FAQ?
   0.04: What are some must-have books on graphics algorithms?
   0.05: Are there any online references?
   0.06: Are there other graphics related FAQs?
   0.07: Where is all the source?

1. 2D Computations: Points, Segments, Circles, Etc.
   1.01: How do I rotate a 2D point?
   1.02: How do I find the distance from a point to a line?
   1.03: How do I find intersections of 2 2D line segments?
   1.04: How do I generate a circle through three points?
   1.05: How can the smallest circle enclosing a set of points be found?
   1.06: Where can I find graph layout algorithms?

2. 2D Polygon Computations
   2.01: How do I find the area of a polygon?
   2.02: How can the centroid of a polygon be computed?
   2.03: How do I find if a point lies within a polygon?
   2.04: How do I find the intersection of two convex polygons?
   2.05: How do I do a hidden surface test (backface culling) with 2D points?
   2.06: How do I find a single point inside a simple polygon?
   2.07: How do I find the orientation of a simple polygon?
   2.08: How can I triangulate a simple polygon?
   2.09: How can I find the minimum area rectangle enclosing a set of points?

3. 2D Image/Pixel Computations
   3.01: How do I rotate a bitmap?
   3.02: How do I display a 24 bit image in 8 bits?
   3.03: How do I fill the area of an arbitrary shape?
   3.04: How do I find the 'edges' in a bitmap?
   3.05: How do I enlarge/sharpen/fuzz a bitmap?
   3.06: How do I map a texture on to a shape?
   3.07: How do I detect a 'corner' in a collection of points?
   3.08: Where do I get source to display (raster font format)?
   3.09: What is morphing/how is it done?
   3.10: How do I quickly draw a filled triangle?
   3.11: D Noise functions and turbulence in Solid texturing.
   3.12: How do I generate realistic sythetic textures?
   3.13: How do I convert between color models (RGB, HLS, CMYK, CIE etc)?
   3.14: How is "GIF" pronounced?

4. Curve Computations
   4.01: How do I generate a Bezier curve that is parallel to another Bezier?
   4.02: How do I split a Bezier at a specific value for t?
   4.03: How do I find a t value at a specific point on a Bezier?
   4.04: How do I fit a Bezier curve to a circle?

5. 3D computations
   5.01: How do I rotate a 3D point?
   5.02: What is ARCBALL and where is the source?
   5.03: How do I clip a polygon against a rectangle?
   5.04: How do I clip a polygon against another polygon?
   5.05: How do I find the intersection of a line and a plane?
   5.06: How do I determine the intersection between a ray and a triangle?
   5.07: How do I determine the intersection between a ray and a sphere?
   5.08: How do I find the intersection of a ray and a Bezier surface?
   5.09: How do I ray trace caustics?
   5.10: What is the marching cubes algorithm?
   5.11: What is the status of the patent on the "marching cubes" algorithm?
   5.12: How do I do a hidden surface test (backface culling) with 3D points?
   5.13: Where can I find algorithms for 3D collision detection?
   5.14: How do I perform basic viewing in 3D?
   5.15: How do I optimize/simplify a 3D polygon mesh?
   5.16: How can I perform volume rendering?
   5.17: Where can I get the spline description of the famous teapot etc.?
   5.18: How can the distance between two lines in space be computed?
   5.19: How can I compute the volume of a polyhedron?
   5.20: How can I decompose a polyhedron into convex pieces?
   5.21: How can the circumsphere of a tetrahedron be computed?
   5.22: How do I determine if two triangles in 3D intersect?
   5.23: How can a 3D surface be reconstructed from a collection of points?
   5.24: How can I find the smallest sphere enclosing a set of points in 3D? 
   5.25: What's the big deal with quaternions?
   5.26: How can I aim a camera in a specific direction?
   5.27: How can I transform normals?


6. Geometric Structures and Mathematics
   6.01: Where can I get source for Voronoi/Delaunay triangulation?
   6.02: Where do I get source for convex hull?
   6.03: Where do I get source for halfspace intersection?
   6.04: What are barycentric coordinates?
   6.05: How do I generate a random point inside a triangle?
   6.06: How do I evenly distribute N points on (tesselate) a sphere?
   6.07: What are coordinates for the vertices of an icosohedron?
   6.08: How do I generate random points on the surface of a sphere?
   6.09: What are Plucker coordinates?

7. Contributors
   7.01: How can you contribute to this FAQ?
   7.02: Contributors.  Who made this all possible.

Search e.g. for "Section 6" to find that section.
Search e.g. for "Subject 6.04" to find that item.
----------------------------------------------------------------------
Section 0. General Information
----------------------------------------------------------------------
Subject 0.01: Charter of comp.graphics.algorithms

    comp.graphics.algorithms is an unmoderated newsgroup intended as a forum
    for the discussion of the algorithms used in the process of generating
    computer graphics.  These algorithms may be recently proposed in
    published journals or papers, old or previously known algorithms, or
    hacks used incidental to the process of computer graphics.  The scope of
    these algorithms may range from an efficient way to multiply matrices,
    all the way to a global illumination method incorporating raytracing,
    radiosity, infinite spectrum modeling, and perhaps even mirrored balls
    and lime jello.

    It is hoped that this group will serve as a forum for programmers and
    researchers to exchange ideas and ask questions on recent papers or
    current research related to computer graphics.

    comp.graphics.algorithms is not:

     - for requests for gifs, or other pictures
     - for requests for image translator or processing software; see
            alt.binaries.pictures* FAQ  
            alt.binaries.pictures.utilities [now degenerated to pic postings]
            alt.graphics.pixutils (image format translation)
            comp.sources.misc (image viewing source code)
            sci.image.processing
            comp.graphics.apps.softimage
            fj.comp.image
     - for requests for compression software; for these try:
            alt.comp.compression
            comp.compression
            comp.compression.research
     - specifically for game development; for this try:
            comp.games.development.programming.misc
            comp.games.development.programming.algorithms


----------------------------------------------------------------------
Subject 0.02: Are the postings to comp.graphics.algorithms archived?

    Archives may be found at: http://www.faqs.org/

----------------------------------------------------------------------
Subject 0.03: How can I get this FAQ?

    The FAQ is posted on the 1st and 15th of every month.  The easiest
    way to get it is to search back in your news reader for the most
    recent posting, with Subject: 
          comp.graphics.algorithms Frequently Asked Questions
    It is posted to comp.graphics.algorithms, and cross-posted to
    news.answers and comp.answers.  

    If you can't find it on your newsreader,
    you can look at a recent HTML version at the "official" FAQ archive site:
      http://www.faqs.org/
    The maintainer also keeps a copy of the raw ASCII, always the
    latest version, accessible via http://cs.smith.edu/~orourke/FAQ.html .

    Finally, you can ftp the FAQ from several sites, including:

      ftp://rtfm.mit.edu/pub/faqs/graphics/algorithms-faq
      ftp://mirror.seas.gwu.edu/pub/rtfm/comp/graphics/algorithms/

    The (busy) rtfm.mit.edu site lists many alternative "mirror" sites.
    Also can reach the FAQ from http://www.geom.umn.edu/software/cglist/,
    which is worth visiting in its own right.

----------------------------------------------------------------------
Subject 0.04: What are some must-have books on graphics algorithms?

    The keywords in brackets are used to refer to the books in later
    questions.  They generally refer to the first author except where
    it is necessary to resolve ambiguity or in the case of the Gems.


    Basic computer graphics, rendering algorithms,
    ----------------------------------------------

    [Foley]
    Computer Graphics: Principles and Practice (2nd Ed.),
    J.D. Foley, A. van Dam, S.K. Feiner, J.F. Hughes, Addison-Wesley
    1990, ISBN 0-201-12110-7;
    Computer Graphics: Principles and Practice, C version
    J.D. Foley,  A. van Dam, S.K. Feiner, J.F. Hughes, Addison-Wesley 
    ISBN: 0-201-84840-6, 1996, 1147 pp.

    [Rogers:Procedural]
    Procedural Elements for Computer Graphics, Second Edition
    David F. Rogers, WCB/McGraw Hill 1998, ISBN 0-07-053548-5

    [Rogers:Mathematical]
    Mathematical Elements for Computer Graphics 2nd Ed.,
    David F. Rogers and J. Alan Adams, McGraw Hill 1990, ISBN
    0-07-053530-2

    [Watt:3D]
    _3D Computer Graphics, 2nd Edition_,
    Alan Watt, Addison-Wesley 1993, ISBN 0-201-63186-5

    [Glassner:RayTracing]
    An Introduction to Ray Tracing,
    Andrew Glassner (ed.), Academic Press 1989, ISBN 0-12-286160-4

    [Gems I]
    Graphics Gems,
    Andrew Glassner (ed.), Academic Press 1990, ISBN 0-12-286165-5
    http://www.graphicsgems.org/ for all the Gems.

    [Gems II]
    Graphics Gems II,
    James Arvo (ed.), Academic Press 1991, ISBN 0-12-64480-0

    [Gems III]
    Graphics Gems III,
    David Kirk (ed.), Academic Press 1992, ISBN 0-12-409670-0 (with
    IBM disk) or 0-12-409671-9 (with Mac disk)
    See also "AP Professional Graphics CD-ROM Library,"
    Academic Press,  ISBN 0-12-059756-X, which contains Gems I-III.

    [Gems IV]
    Graphics Gems IV,
    Paul S. Heckbert (ed.), Academic Press 1994, ISBN 0-12-336155-9
    (with IBM disk) or 0-12-336156-7 (with Mac disk)

    [Gems V]
    Graphic Gems V,
    Alan W. Paeth (ed.), Academic Press 1995, ISBN 0-12-543455-3
    (with IBM disk)

    [Watt:Animation]
    Advanced Animation and Rendering Techniques,
    Alan Watt, Mark Watt, Addison-Wesley 1992, ISBN 0-201-54412-1
    (Unofficial) errata: http://www.rolemaker.dk/other/AART/

    [Bartels]
    An Introduction to Splines for Use in Computer Graphics and
        Geometric Modeling,
    Richard H. Bartels, John C. Beatty, Brian A. Barsky, 1987, ISBN
    0-934613-27-3

    [Farin]
    Curves and Surfaces for Computer Aided Geometric Design:
    A Practical Guide, 4th Edition, Gerald E. Farin, Academic Press
    1996. ISBN 0122490541.

    [Prusinkiewicz]
    The Algorithmic Beauty of Plants,
    Przemyslaw W. Prusinkiewicz, Aristid Lindenmayer, Springer-Verlag,
    1990, ISBN 0-387-97297-8, ISBN 3-540-97297-8

    [Oliver]
    Tricks of the Graphics Gurus,
    Dick Oliver, et al. (2) 3.5 PC disks included, $39.95 SAMS Publishing

    [Hearn]
    Introduction to computer graphics,
    Hearn & Baker

    [Cohen]
    Radiosity and Realistic Imange Sythesis,
    Michael F. Cohen, John R. Wallace, Academic Press Professional
    1993, ISBN 0-12-178270-0 [limited reprint 1999]

    [Ashdown]
    Radiosity: A Programmer's Perspective
    Ian Ashdown, John Wiley & Sons 1994, ISBN 0-471-30444-1, 498 pp.
    Back in print, Jan 2003.  See www.helios32.com.

    [sillion]
    Radiosity & Global Illumination
    Francois X. Sillion snd Claude Puech, Morgan Kaufmann 1994, ISBN
    1-55860-277-1, 252 pp.

    [Ebert]
    Texturing and Modeling - A Procedural Approach (2nd Ed.)
    David S. Ebert (ed.), F. Kenton Musgrave, Darwyn Peachey, Ken Perlin,
    Steven Worley, Academic Press 1998, ISBN 0-12-228730-4, Includes CD-ROM.

    [Schroeder]
    Visualization Toolkit, 2nd Edition, The: An Object-Oriented Approach to
    3-D Graphics (Bk/CD) (Professional Description)
    William J. Schroeder,  Kenneth Martin, and Bill Lorensen,
    Prentice-Hall 1998, ISBN: 0-13-954694-4
    See Subject 0.07 for source.

    [Anderson]
    PC Graphics Unleashed
    Scott Anderson. SAMS Publishing, ISBN 0-672-30570-4

    [Ammeraal]
    Computer Graphics for Java Programmers,
    Leen Ammeraal, John Wiley 1998, ISBN 0-471-98142-7.
    Additional information at http://home.wxs.nl/~ammeraal/ .

    [Eberly]
    3D Game Engine Design: A Practical Approach to Real-Time Computer Graphics.
    David Eberly, Morgan Kaufmann/Academic Press, 2001.

    For image processing,
    ---------------------

    [Barnsley]
    Fractal Image Compression,
    Michael F. Barnsley and Lyman P. Hurd, AK Peters, Ltd, 1993 ISBN
    1-56881-000-8

    [Jain]
    Fundamentals of Image Processing,
    Anil K. Jain, Prentice-Hall 1989, ISBN 0-13-336165-9

    [Castleman]
    Digital Image Processing,
    Kenneth R. Castleman, Prentice-Hall 1996, ISBN(Cloth): 0-13-211467-4
    (Description and errata at: "http://www.phoenix.net/~castlman")

    [Pratt]
    Digital Image Processing, Second Edition,
    William K. Pratt, Wiley-Interscience 1991, ISBN 0-471-85766-1

    [Gonzalez]
    Digital Image Processing (3rd Ed.),
    Rafael C. Gonzalez, Paul Wintz, Addison-Wesley 1992, ISBN
    0-201-50803-6

    [Russ]
    The Image Processing Handbook (3rd Ed.),
    John C. Russ, CRC Press and IEEE Press 1998, ISBN 0-8493-2532-3
    [Russ & Russ]
    The Image Processing Tool Kit v. 3.0
    Chris Russ and John Russ, Reindeer Games Inc. 1999, ISBN 1-928808-00-X


    [Wolberg]
    Digital Image Warping,
    George Wolberg, IEEE Computer Society Press Monograph 1990, ISBN
    0-8186-8944-7


    Computational geometry
    ----------------------

    [Bowyer]
    A Programmer's Geometry,
    Adrian Bowyer, John Woodwark, Butterworths 1983, 
    ISBN 0-408-01242-0 Pbk
    Out of print, but see:
    Introduction to Computing with Geometry,
    Adrian Bowyer and John Woodwark, 1993
    ISBN 1-874728-03-8.  Available in PDF:
       http://www.inge.com/pubs/index.htm

    [Farin & Hansford]
    The Geometry Toolbox for Graphics and Modeling
    by Gerald E. Farin, Dianne Hansford
    A K Peters Ltd; ISBN: 1568810741 

    [O'Rourke (C)]
    Computational Geometry in C (2nd Ed.)
    Joseph O'Rourke, Cambridge University Press 1998, 
    ISBN 0-521-64010-5 Pbk, ISBN 0-521-64976-5 Hbk
    Additional information and code at http://cs.smith.edu/~orourke/ .

    [O'Rourke (A)]
    Art Gallery Theorems and Algorithms
    Joseph O'Rourke, Oxford University Press 1987,
    ISBN 0-19-503965-3.

    [Goodman & O'Rourke]
    Handbook of Discrete and Computational Geometry
    J. E. Goodman and J. O'Rourke, editors.
    CRC Press LLC, July 1997.
    ISBN:0-8493-8524-5
    Additional information at http://cs.smith.edu/~orourke/ .

    [Samet:Application]
    Applications of Spatial Data Structures:  Computer Graphics, 
    Image Processing, and GIS, 
    Hanan Samet, Addison-Wesley, Reading, MA, 1990.
    ISBN 0-201-50300-0.

    [Samet:Design & Analysis]
    The Design and Analysis of Spatial Data Structures,
    Hanan Samet, Addison-Wesley, Reading, MA, 1990.
    ISBN 0-201-50255-0.

    [Mortenson]
    Geometric Modeling,
    Michael E. Mortenson, Wiley 1985, ISBN 0-471-88279-8

    [Preparata]
    Computational Geometry: An Introduction,
    Franco P. Preparata, Michael Ian Shamos, Springer-Verlag 1985,
    ISBN 0-387-96131-3

    [Okabe]
    Spatial Tessellations: Concepts and Applications of Voronoi Diagrams,
    A. Okabe and B. Boots and K. Sugihara,
    John Wiley, Chichester, England, 1992.

    [Overmars]
    Computational Geometry: Algorithms and Applications
    M. de Berg and M. van Kreveld and M. Overmars and O. Schwarzkopf
    Springer-Verlag, Berlin, 1997.

    [Stolfi]
    Oriented Projective Geometry: A Framework for Geometric Computations
    Academic Press, 1991.

    [Hodge]
    Methods of Algebraic Geometry, Volume 1
    W.V.D. Hodge and D. Pedoe, Cambridge, 1994.
    ISBN 0-521-469007-4 Paperback

    [Tamassia et al 199?]
    Graph Drawing: Algorithms for the Visualization of Graphs
    Prentice Hall; ISBN: 0133016153

    Algorithms books with chapters on computational geometry
    --------------------------------------------------------

    [Cormen et al.]
    Introduction to Algorithms,
    T. H. Cormen, C. E. Leiserson, R. L. Rivest,
    The MIT Press, McGraw-Hill, 1990.

    [Mehlhorn]
    Data Structures and Algorithms,
    K. Mehlhorn,
    Springer-Verlag, 1984.

    [Sedgewick]
    R. Sedgewick,
    Algorithms,
    Addison-Wesley, 1988.

    Solid Modelling
    ---------------

    [Mantyla]
    Introduction to Solid Modeling
    Martti Mantyla, Computer Science Press 1988,
    ISBN 07167-8015-1

----------------------------------------------------------------------
Subject 0.05: Are there any online references?

    The computational geometry community maintains its own
    bibliography of publications in or closely related to that
    subject.  Every four months, additions and corrections are
    solicited from users, after which the database is updated and
    released anew.  As of 7 Nov 200, it contained 13485 bib-tex
    entries.  See Jeff Erickson's page on "Computational Geometry
    Bibliographies": 
      http://compgeom.cs.uiuc.edu/~jeffe/compgeom/biblios.html#geombib
    The bibliography can be retrieved from:

    ftp://ftp.cs.usask.ca/pub/geometry/geombib.tar.gz - bibliography proper
    ftp://ftp.cs.usask.ca/pub/geometry/o-cgc19.ps.gz  - overview published
        in '93 in SIGACT News and the Internat. J. Comput.  Geom. Appl.
    ftp://ftp.cs.usask.ca/pub/geometry/ftp-hints      - detailed retrieval info

    Universitat Politecnica de Catalunya maintains a search engine at:
       http://www-ma2.upc.es/~geomc/geombibe.html

    The ACM SIGGRAPH Online Bibliography Project, by
    Stephen Spencer (biblio@siggraph.org).
    The database is available for anonymous FTP from the
    ftp://siggraph.org/publications/ directory.  Please
    download and examine the file READ_ME in that directory for more
    specific information concerning the database.

    'netlib' is a useful source for algorithms, member inquiries for
    SIAM, and bibliographic searches.  For information, send mail to
    netlib@ornl.gov, with "send index" in the body of the mail
    message.

    You can also find free sources for numerical computation in C via
    ftp://ftp.usc.edu/pub/C-numanal/ . In particular, grab
    numcomp-free-c.gz in that directory.

    Check out Nick Fotis's computer graphics resources FAQ -- it's
    packed with pointers to all sorts of great computer graphics
    stuff.  This FAQ is posted biweekly to comp.graphics.

    This WWW page contains links to a large number
    of computer graphic related pages:
    http://www.dataspace.com:84/vlib/comp-graphics.html

    There's a Computer Science Bibliography Server at:
    http://glimpse.cs.arizona.edu:1994/bib/
    with Computer Graphics, Vision and Radiosity sections

    A comprehensive bibliography of color quantization papers and articles 
    (CQUANT97) was available at http://www.ledalite.com/library-/cgis.htm.
    [Link no longer available -- replacement? --JOR]

    Modelling physically based systems for animation:
    http://www.cc.gatech.edu/gvu/animation/Animation.html

    The University of Manchester NURBS Library:
    ftp://unix.hensa.ac.uk/pub/misc/unix/nurbs/

    For an implementation of Seidel's algorithm for fast trapezoidation
    and triangulation of polygons. You can get the code from:
    ftp://ftp.cs.unc.edu/pub/users/narkhede/triangulation.tar.gz

    Ray tracing bibliography:
    http://www.acm.org/tog/resources/bib/

    Quaternions and other comp sci curiosities:
    ftp://ftp.netcom.com/pub/hb/hbaker/hakmem/

    Directory of Computational Geometry Software,
    collected by Nina Amenta (nina@cs.utexas.edu)
    Nina Amenta is maintaining a WWW directory to computational 
    geometry software. The directory lives at The Geometry Center. 
    It has pointers to lots of convex hull and voronoi diagram programs, 
    triangulations, collision detection, polygon intersection, smallest 
    enclosing ball of a point set and other stuff.
    http://www.geom.umn.edu/software/cglist/

    A compact reference for real-time 3D computer graphics programming:
    http://www.math.mcgill.ca/~loisel/

    RADBIB is a comprehensive bibliography of radiosity and
    related global illumination papers, articles, and
    books. It currently includes 1,972 references.
    This bibliography is available in BibTex format 
    (with a release date of 15 Jul 01) from:
      http://www.helios32.com/   under "Resources."

    The "Electronic Visualization Library" (EVlib) is a domain-
    secific digital library for Scientific Visualization and 
    Computer Graphics:  http://visinfo.zib.de/

    3D Object Intersection: http://www.realtimerendering.com/int/ 
    This page presents information about a wide variety of 3D object/object
    intersection tests. Presented in grid form, each axis lists ray, plane,
    sphere, triangle, box, frustum, and other objects. For each combination
    (e.g. sphere/box), references to articles, books, and online resources
    are given.

    Ray Tracing News, ed. Eric Haines:  http://www.raytracingnews.com .

----------------------------------------------------------------------
Subject 0.06: Are there other graphics related FAQs?

    BSP Tree FAQ by Bretton Wade
 	http://www.andrew.cmu.edu/~rrost/bsp/
 	ftp://ftp.sgi.com/other/bspfaq/faq/bspfaq.html
 	ftp://ftp.sgi.com/other/bspfaq/faq/bspfaq.txt
     and see
 	ftp://ftp.sgi.com/other/bspfaq/

    Gamma and Color FAQs by Charles A. Poynton has
        ftp://ftp.inforamp.net/pub/users/poynton/doc/colour/
        http://www.inforamp.net/~poynton/

    The documents are mirrored in Darmstadt, Germany at
        ftp://ftp.igd.fhg.de/pub/doc/colour/

----------------------------------------------------------------------
Subject 0.07: Where is all the source?

    Graphics Gems source code.
    http://www.graphicsgems.org
    This site is now the offical distribution site for Graphics Gems code.

    Master list of Computational Geometry software:
    http://www.geom.umn.edu/software/cglist
    Described in [Goodman & O'Rourke], Chap. 52.

    Jeff Erikson's software list:
    http://compgeom.cs.uiuc.edu/~jeffe/compgeom/compgeom.html

    Dave Eberly's extensive collection of free geometry, graphics,
    and image processing software:
    http://www.magic-software.com/

    General 'stuff'
    ftp://wuarchive.wustl.edu/graphics/

    There are a number of interesting items in
    http://graphics.lcs.mit.edu/~seth including:
    - Code for 2D Voronoi, Delaunay, and Convex hull
    - Mike Hoymeyer's implementation of Raimund Seidel's
      O( d! n ) time linear programming algorithm for
      n constraints in d dimensions
    - geometric models of UC Berkeley's new computer science
      building

    Sources to "Computational Geometry in C", by J. O'Rourke
    can be found at http://cs.smith.edu/~orourke/books/compgeom.html
    or ftp://cs.smith.edu/pub/compgeom .

    Greg Ferrar's C++ 3D rendering library is available at
    http://www.flowerfire.com/ferrar/Graph3D.html  

    TAGL is a portable and extensible library that provides a subset
    of Open-GL functionalities.
    ftp://sunsite.unc.edu/pub/packages/programming/graphics/

    Try ftp://x2ftp.oulu.fi  for /pub/msdos/programming/docs/graphpro.lzh by
    Michael Abrash. His XSharp package has an implementation of Xiaoulin
    Wu's anti-aliasing algorithm (in C).

    Example sources for BSP tree algorithms can be found at
    http://reality.sgi.com/bspfaq/, item 24.

    Mel Slater (mel@dcs.qmw.ac.uk) also made some implementations of
    BSP trees and shadows for static scenes using shadow volumes
    code available
    http://www.dcs.qmw.ac.uk/~mel/BSP.html
    ftp://ftp.dcs.qmw.ac.uk/people/mel/BSP

    The Visualization Toolkit (A visualization textbook, C++ library 
    and Tcl-based interpreter) (see [Schroeder]): 
    http://www.kitware.com/vtk.html

    WINGED.ZIP, a C++ implementation of Baumgart's winged-edge data structure:
    ftp://ftp.ledalite.com/pub/   

    CGAL, the Computational Geometry Algorithms Library, is written in C++ 
    and is available at http://www.cgal.org.  
    CGAL contains algorithms and data structures for 2D computations
    (convex hull, Delaunay, constrained Delaunay, Voronoi diagram, 
    regular traingulation, (weighted) Alpha shapes, polytope distance, 
    boolean operations on polygons, decomposition of polygons in
    monotone or convex parts, arrangements, etc.), 3D, and arbitrary
    dimensions.

    A C++ NURBS library written by Lavoie Philippe. Version 2.1. 
    Results may be exported as POV-Ray, RIB (renderman) or VRML files.
    It also offers wrappers to OpenGL:
       http://yukon.genie.uottawa.ca/~lavoie/software/nurbs/

    Paul Bourke has code for several problems, including isosurface 
    generation and Delauney triangulation, at:
       http://www.swin.edu.au/astronomy/pbourke/geometry/
       http://www.swin.edu.au/astronomy/pbourke/modeling/

    A nearly comprehensive list of available 3D engines 
    (most with source code):
       http://cg.cs.tu-berlin.de/~ki/engines.html

    See also 5.17: 
        Where can I get the spline description of the famous teapot etc.?

    Interactive Geometry Software called "Cinderella":
        http://www.cinderella.de

----------------------------------------------------------------------
Section 1. 2D Computations: Points, Segments, Circles, Etc.
----------------------------------------------------------------------
Subject 1.01: How do I rotate a 2D point?

    In 2D, you make (X,Y) from (x,y) with a rotation by angle t so:
        X = x cos t - y sin t
        Y = x sin t + y cos t
    As a 2x2 matrix this is very simple.  If you want to rotate a
    column vector v by t degrees using matrix M, use
        M = [cos t  -sin t]
            [sin t   cos t]
    in the product M v.

    If you have a row vector, use the transpose of M (turn rows into
    columns and vice versa).  If you want to combine rotations, in 2D
    you can just add their angles, but in higher dimensions you must
    multiply their matrices.

----------------------------------------------------------------------
Subject 1.02: How do I find the distance from a point to a line?


    Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
    Let P be the point of perpendicular projection of C on AB.  The parameter
    r, which indicates P's position along AB, is computed by the dot product 
    of AC and AB divided by the square of the length of AB:
    
    (1)     AC dot AB
        r = ---------  
            ||AB||^2
    
    r has the following meaning:
    
        r=0      P = A
        r=1      P = B
        r<0      P is on the backward extension of AB
        r>1      P is on the forward extension of AB
        0<r<1    P is interior to AB
    
    The length of a line segment in d dimensions, AB is computed by:
    
        L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)

    so in 2D:   
    
        L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
    
    and the dot product of two vectors in d dimensions, U dot V is computed:
    
        D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
    
    so in 2D:   
    
        D = (Ux * Vx) + (Uy * Vy) 
    
    So (1) expands to:
    
            (Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
        r = -------------------------------
                          L^2

    The point P can then be found:

        Px = Ax + r(Bx-Ax)
        Py = Ay + r(By-Ay)

    And the distance from A to P = r*L.

    Use another parameter s to indicate the location along PC, with the 
    following meaning:
           s<0      C is left of AB
           s>0      C is right of AB
           s=0      C is on AB

    Compute s as follows:

            (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
        s = -----------------------------
                        L^2


    Then the distance from C to P = |s|*L.


----------------------------------------------------------------------
Subject 1.03: How do I find intersections of 2 2D line segments?

    This problem can be extremely easy or extremely difficult; it
    depends on your application. If all you want is the intersection
    point, the following should work:

    Let A,B,C,D be 2-space position vectors.  Then the directed line
    segments AB & CD are given by:

        AB=A+r(B-A), r in [0,1]
        CD=C+s(D-C), s in [0,1]

    If AB & CD intersect, then

        A+r(B-A)=C+s(D-C), or

        Ax+r(Bx-Ax)=Cx+s(Dx-Cx)
        Ay+r(By-Ay)=Cy+s(Dy-Cy)  for some r,s in [0,1]

    Solving the above for r and s yields

            (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
        r = -----------------------------  (eqn 1)
            (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)

            (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
        s = -----------------------------  (eqn 2)
            (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)

    Let P be the position vector of the intersection point, then

        P=A+r(B-A) or

        Px=Ax+r(Bx-Ax)
        Py=Ay+r(By-Ay)

    By examining the values of r & s, you can also determine some
    other limiting conditions:

        If 0<=r<=1 & 0<=s<=1, intersection exists
            r<0 or r>1 or s<0 or s>1 line segments do not intersect

        If the denominator in eqn 1 is zero, AB & CD are parallel
        If the numerator in eqn 1 is also zero, AB & CD are collinear.

    If they are collinear, then the segments may be projected to the x- 
    or y-axis, and overlap of the projected intervals checked.

    If the intersection point of the 2 lines are needed (lines in this
    context mean infinite lines) regardless whether the two line
    segments intersect, then

        If r>1, P is located on extension of AB
        If r<0, P is located on extension of BA
        If s>1, P is located on extension of CD
        If s<0, P is located on extension of DC

    Also note that the denominators of eqn 1 & 2 are identical.

    References:

    [O'Rourke (C)] pp. 249-51
    [Gems III] pp. 199-202 "Faster Line Segment Intersection,"

----------------------------------------------------------------------
Subject 1.04: How do I generate a circle through three points?

    Let the three given points be a, b, c.  Use _0 and _1 to represent
    x and y coordinates. The coordinates of the center p=(p_0,p_1) of
    the circle determined by a, b, and c are:

        A = b_0 - a_0;
        B = b_1 - a_1;
        C = c_0 - a_0;
        D = c_1 - a_1;
    
        E = A*(a_0 + b_0) + B*(a_1 + b_1);
        F = C*(a_0 + c_0) + D*(a_1 + c_1);
    
        G = 2.0*(A*(c_1 - b_1)-B*(c_0 - b_0));
    
        p_0 = (D*E - B*F) / G;
        p_1 = (A*F - C*E) / G;
 
    If G is zero then the three points are collinear and no finite-radius
    circle through them exists.  Otherwise, the radius of the circle is:

            r^2 = (a_0 - p_0)^2 + (a_1 - p_1)^2

    Reference:

    [O' Rourke (C)] p. 201. Simplified by Jim Ward.

----------------------------------------------------------------------
Subject 1.05: How can the smallest circle enclosing a set of points be found?

    This circle is often called the minimum spanning circle.  It can be
    computed in O(n log n) time for n points.  The center lies on
    the furthest-point Voronoi diagram.  Computing the diagram constrains
    the search for the center.  Constructing the diagram can be accomplished
    by a 3D convex hull algorithm; for that connection, see, e.g.,
    [O'Rourke (C), p.195ff].  For direct algorithms, see:
      S. Skyum, "A simple algorithm for computing the smallest enclosing circle"
      Inform. Process. Lett. 37 (1991) 121--125.
      J. Rokne, "An Easy Bounding Circle" [Gems II] pp.14--16.

----------------------------------------------------------------------
Subject 1.06: Where can I find graph layout algorithms?

    See the paper by Eades and Tamassia, "Algorithms for Drawing
    Graphs: An Annotated Bibliography," Tech Rep CS-89-09, Dept.  of
    CS, Brown Univ, Feb. 1989.

    A revised version of the annotated bibliography on graph drawing
    algorithms by Giuseppe Di Battista, Peter Eades, and Roberto
    Tamassia is now available from

    ftp://wilma.cs.brown.edu/pub/papers/compgeo/gdbiblio.tex.gz and
    ftp://wilma.cs.brown.edu/pub/papers/compgeo/gdbiblio.ps.gz

    Commercial software includes the Graph Layout Toolkit from Tom Sawyer
    Software http://www.tomsawyer.com and Northwoods Software's GO++
    http://www.nwoods.com/go/ .

    Perhaps the best code is the AT&T Research Labs open C source:
    http://www.research.att.com/sw/tools/graphviz/

----------------------------------------------------------------------
Section 2. 2D Polygon Computations
----------------------------------------------------------------------
Subject 2.01: How do I find the area of a polygon?

    The signed area can be computed in linear time by a simple sum.
    The key formula is this:

        If the coordinates of vertex v_i are x_i and y_i,
        twice the signed area of a polygon is given by

        2 A( P ) = sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1}).

    Here n is the number of vertices of the polygon, and index
    arithmetic is mod n, so that x_n = x_0, etc. A rearrangement
    of terms in this equation can save multiplications and operate on
    coordinate differences, and so may be both faster and more
    accurate:

       2 A(P) = sum_{i=0}^{n-1} ( x_i  (y_{i+1} - y_{i-1}) )

    Here again modular index arithmetic is implied, with n=0 and -1=n-1.
    This can be avoided by extending the x[] and y[] arrays up to [n+1]
    with x[n]=x[0], y[n]=y[0] and y[n+1]=y[1], and using instead

       2 A(P) = sum_{i=1}^{n} ( x_i  (y_{i+1} - y_{i-1}) )


    References: [O' Rourke (C)] Thm. 1.3.3, p. 21; [Gems II] pp. 5-6:
    "The Area of a Simple Polygon", Jon Rokne.  Dan Sunday's explanation:
       http://GeometryAlgorithms.com/Archive/algorithm_0101/  where

    To find the area of a planar polygon not in the x-y plane, use:
    
       2 A(P) = abs(N . (sum_{i=0}^{n-1} (v_i x v_{i+1})))
    
       where N is a unit vector normal to the plane. The `.' represents the
       dot product operator, the `x' represents the cross product operator,
       and abs() is the absolute value function.
    
    [Gems II] pp. 170-171:
    "Area of Planar Polygons and Volume of Polyhedra", Ronald N. Goldman.

----------------------------------------------------------------------
Subject 2.02: How can the centroid of a polygon be computed?

    The centroid (a.k.a. the center of mass, or center of gravity)
    of a polygon can be computed as the weighted sum of the centroids
    of a partition of the polygon into triangles.  The centroid of a
    triangle is simply the average of its three vertices, i.e., it
    has coordinates (x1 + x2 + x3)/3 and (y1 + y2 + y3)/3.  This 
    suggests first triangulating the polygon, then forming a sum
    of the centroids of each triangle, weighted by the area of
    each triangle, the whole sum normalized by the total polygon area.
    This indeed works, but there is a simpler method:  the triangulation
    need not be a partition, but rather can use positively and
    negatively oriented triangles (with positive and negative areas),
    as is used when computing the area of a polygon.  This leads to
    a very simple algorithm for computing the centroid, based on a
    sum of triangle centroids weighted with their signed area.
    The triangles can be taken to be those formed by any fixed point,
    e.g., the vertex v0 of the polygon, and the two endpoints of 
    consecutive edges of the polygon: (v1,v2), (v2,v3), etc.  The area 
    of a triangle with vertices a, b, c is half of this expression:
                (b[X] - a[X]) * (c[Y] - a[Y]) -
                (c[X] - a[X]) * (b[Y] - a[Y]);
 
    Code available at ftp://cs.smith.edu/pub/code/centroid.c (3K).
    Reference: [Gems IV] pp.3-6; also includes code.

----------------------------------------------------------------------
Subject 2.03: How do I find if a point lies within a polygon?

    The definitive reference is "Point in Polygon Strategies" by
    Eric Haines [Gems IV]  pp. 24-46.  Now also at 
       http://www.erichaines.com/ptinpoly.
    The code in the Sedgewick book Algorithms (2nd Edition, p.354) fails
    under certain circumstances.  See 
       http://condor.informatik.Uni-Oldenburg.DE/~stueker/graphic/index.html
    for a discussion.

    The essence of the ray-crossing method is as follows.
    Think of standing inside a field with a fence representing the polygon. 
    Then walk north. If you have to jump the fence you know you are now 
    outside the poly. If you have to cross again you know you are now 
    inside again; i.e., if you were inside the field to start with, the total 
    number of fence jumps you would make will be odd, whereas if you were 
    ouside the jumps will be even.

    The code below is from Wm. Randolph Franklin <wrf@ecse.rpi.edu>
    (see URL below) with some minor modifications for speed.  It returns 
    1 for strictly interior points, 0 for strictly exterior, and 0 or 1 
    for points on the boundary.  The boundary behavior is complex but 
    determined; in particular, for a partition of a region into polygons, 
    each point is "in" exactly one polygon.  
    (See p.243 of [O'Rourke (C)] for a discussion of boundary behavior.)

    int pnpoly(int npol, float *xp, float *yp, float x, float y)
    {
      int i, j, c = 0;
      for (i = 0, j = npol-1; i < npol; j = i++) {
        if ((((yp[i]<=y) && (y<yp[j])) ||
             ((yp[j]<=y) && (y<yp[i]))) &&
            (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))

          c = !c;
      }
      return c;
    }

    The code may be further accelerated, at some loss in clarity, by
    avoiding the central computation when the inequality can be deduced,
    and by replacing the division by a multiplication for those processors
    with slow divides.  For code that distinguishes strictly interior
    points from those on the boundary, see [O'Rourke (C)] pp. 239-245.
    For a method based on winding number, see Dan Sunday,
    "Fast Winding Number Test for Point Inclusion in a Polygon,"
    http://softsurfer.com/algorithms.htm, March 2001.

    References:
    Franklin's code: 
       http://www.ecse.rpi.edu/Homepages/wrf/research/geom/pnpoly.html
    [Gems IV]  pp. 24-46
    [O'Rourke (C)] Sec. 7.4.
    [Glassner:RayTracing]

----------------------------------------------------------------------
Subject 2.04: How do I find the intersection of two convex polygons?

    Unlike intersections of general polygons, which might produce a
    quadratic number of pieces, intersection of convex polygons of n
    and m vertices always produces a polygon of at most (n+m) vertices.
    There are a variety of algorithms whose time complexity is proportional
    to this size, i.e., linear.  The first, due to Shamos and Hoey, is
    perhaps the easiest to understand.  Let the two polygons be P and
    Q.  Draw a horizontal line through every vertex of each.  This
    partitions each into trapezoids (with at most two triangles, one
    at the top and one at the bottom).  Now scan down the two polygons
    in concert, one trapezoid at a time, and intersect the trapezoids
    if they overlap vertically.
       A more difficult-to-describe algorithm is in [O'Rourke (C)], pp. 252-262.
    This walks around the boundaries of P and Q in concert, intersecting
    edges.  An implementation is included in [O'Rourke (C)].


----------------------------------------------------------------------
Subject 2.05: How do I do a hidden surface test (backface culling) with 2D points?

    c = (x1-x2)*(y3-y2)-(y1-y2)*(x3-x2)

    x1,y1, x2,y2, x3,y3 = the first three points of the polygon.

    If c is positive the polygon is visible. If c is negative the
    polygon is invisible (or the other way).


----------------------------------------------------------------------
Subject 2.06: How do I find a single point inside a simple polygon?

   Given a simple polygon, find some point inside it.  Here is a method
   based on the proof that there exists an internal diagonal, in
   [O'Rourke (C), 13-14].  The idea is that the midpoint of a diagonal
   is interior to the polygon.
 
   1. Identify a convex vertex v; let its adjacent vertices be a and b.
   2. For each other vertex q do:
   	2a. If q is inside avb, compute distance to v (orthogonal to ab).
   	2b. Save point q if distance is a new min.
   3. If no point is inside, return midpoint of ab, or centroid of avb.
   4. Else if some point inside, qv is internal: return its midpoint.
 
   Code for finding a diagonal is in [O'Rourke (C), 35-39], and is part
   of many other software packages.  See Subject 0.07: Where is all the 
   source?

----------------------------------------------------------------------
Subject 2.07: How do I find the orientation of a simple polygon?

    Compute the signed area (Subject 2.01).  The orientation is 
    counter-clockwise if this area is positive.  

    A slightly faster method is based on the observation that it isn't
    necessary to compute the area.  Find the lowest vertex (or, if 
    there is more than one vertex with the same lowest coordinate, 
    the rightmost of those vertices) and then take the cross product 
    of the edges fore and aft of it.  Both methods are O(n) for n vertices, 
    but it does seem a waste to add up the total area when a single cross
    product (of just the right edges) suffices.  Code for this is
    available at ftp://cs.smith.edu/pub/code/polyorient.C (2K).

    The reason that the lowest, rightmost (or any other such extreme) point
    works is that the internal angle at this vertex is necessarily convex, 
    strictly less than pi (even if there are several equally-lowest points).

----------------------------------------------------------------------
Subject 2.08: How can I triangulate a simple polygon?

    Triangulation of a polygon partitions its interior into triangles
    with disjoint interiors.  Usually one restricts corners of the
    triangles to coincide with vertices of the polygon, in which case
    every polygon of n vertices can be triangulated, and all triangulations
    contain n-2 triangles, employing n-3 "diagonals" (chords between
    vertices that otherwise do not touch the boundary of the polygon).
    
    Triangulations can be constructed by a variety of algorithms,
    ranging from a naive search for noncrossing diagonals, which is
    O(n^4), to "ear" clipping, which is O(n^2) and relatively straightforward
    to implement [O'Rourke (C), Chap. 1], to partitioning into
    monotone polygons, which leads to O(n log n) time complexity
    [O'Rourke (C), Chap. 2; Overmars, Chap. 3], to several randomized 
    algorithms---by Clarkson et al., by Seidel, and by Devillers, which 
    lead to O(n log* n) complexity---to Chazelle's linear-time algorithm, 
    which has yet to be implemented.

    There is a tradeoff between code complexity and time complexity.
    Fortunately, several of the algorithms have been implemented and are
    available:
         Ear-clipping: 
                http://cs.smith.edu/~orourke/books/compgeom.html 
                ftp://ftp.cis.uab.edu/pub/sloan/Software/triangulation/src/
         Seidel's Alg: 
                http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html
                ftp://ftp.cs.unc.edu/pub/users/narkhede/triangulation.tar.gz
                http://reality.sgi.com/atul/code/chapter.html
    See also the collection of triangulation links at
                http://www.geom.umn.edu/software/cglist/
    
    References:

    [O'Rourke (C)]
    [Overmars]
    [Gems V]
    Clarkson, K., Tarjan, R., and VanWyk, C. A fast Las Vegas algorithm for
      triangulating a simple polygon. Discrete and Computational Geometry,
      4(1):423--432, 1989.
    Clarkson, K., Cole, R., Tarjan, R. Randomized parallel algorithms for
      trapezoidal diagrams. Int. J. Comp. Geom. Appl., 117--133, 1992.
      http://cm.bell-labs.com/cm/cs/who/clarkson/tri.html
    Seidel, R.  (1991), A simple and fast incremental randomized algorithm for
      computing trapezoidal decompositions and for triangulating polygons,
      Comput. Geom. Theory Appl. 1, 51--64.
    Devillers, O.  (1992), Randomization yields simple O(n log* n)
      algorithms for difficult Omega(n) problems, 
      Internat. J. Comput.  Geom. Appl. 2(1), 97--111.
    Chazelle, B.  (1991), Triangulating a simple polygon in linear time,
      Discrete Comput. Geom. 6, 485--524.
    Held, M. (1998) "FIST: Fast Industrial-Strength Triangulation". 
      http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html

----------------------------------------------------------------------
Subject 2.09: How can I find the minimum area rectangle enclosing a set of points?
    First take the convex hull of the points.  Let the resulting convex
    polygon be P.  It has been known for some time that the minimum
    area rectangle enclosing P must have one rectangle side flush with
    (i.e., collinear with and overlapping) one edge of P.  This geometric
    fact was used by Godfried Toussaint to develop the "rotating calipers"
    algorithm in a hard-to-find 1983 paper, "Solving Geometric Problems 
    with the Rotating Calipers" (Proc. IEEE MELECON).  The algorithm
    rotates a surrounding rectangle from one flush edge to the next,
    keeping track of the minimum area for each edge.  It achieves O(n)
    time (after hull computation).  See the "Rotating Calipers Homepage"
    http://www.cs.mcgill.ca/~orm/rotcal.frame.html for a description
    and applet.

----------------------------------------------------------------------
Section 3. 2D Image/Pixel Computations
----------------------------------------------------------------------
Subject 3.01: How do I rotate a bitmap?

    The easiest way, according to the comp.graphics faq, is to take
    the rotation transformation and invert it. Then you just iterate
    over the destination image, apply this inverse transformation and
    find which source pixel to copy there.

    A much nicer way comes from the observation that the rotation
    matrix:

        R(T) = { { cos(T), -sin(T) }, { sin(T), cos(T) } }

    is formed my multiplying three matrices, namely:

        R(T) = M1(T) * M2(T) * M3(T)

    where

        M1(T) = { { 1, -tan(T/2) },
                  { 0, 1         } }
        M2(T) = { { 1,      0    },
                  { sin(T), 1    } }
        M3(T) = { { 1, -tan(T/2) },
                  { 0,         1 } }

    Each transformation can be performed in a separate pass, and
    because these transformations are either row-preserving or
    column-preserving, anti-aliasing is quite easy.

    Another fast approach is to perform first a column-preserving roation, 
    and then a row-preserving rotation. For an image W pixels wide and 
    H pixels high, this requires W+H BitBlt operations in comparison to 
    the brute-force rotation, which uses W*H SetPixel operations (and a 
    lot of multiplying).

    Reference:

    Paeth, A. W., "A Fast Algorithm for General Raster Rotation",
    Proceedings Graphics Interface '89, Canadian Information
    Processing Society, 1986, 77-81
    [Note - e-mail copies of this paper are no longer available]

    [Gems I]

----------------------------------------------------------------------
Subject 3.02: How do I display a 24 bit image in 8 bits?

    [Gems I] pp. 287-293, "A Simple Method for Color Quantization:
    Octree Quantization"

    B. Kurz.  Optimal Color Quantization for Color Displays.
    Proceedings of the IEEE Conference on Computer Vision and Pattern
    Recognition, 1983, pp. 217-224.

    [Gems II] pp. 116-125, "Efficient Inverse Color Map Computation"

        This describes an efficient technique to
        map actual colors to a reduced color map,
        selected by some other technique described
        in the other papers.

    [Gems II] pp. 126-133, "Efficient Statistical Computations for
    Optimal Color Quantization"

    Xiaolin Wu.  Color Quantization by Dynamic Programming and
    Principal Analysis.  ACM Transactions on Graphics, Vol. 11, No. 4,
    October 1992, pp 348-372.


----------------------------------------------------------------------
Subject 3.03: How do I fill the area of an arbitrary shape?


    "A Fast Algorithm for the Restoration of Images Based on Chain
        Codes Description and Its Applications", L.W. Chang & K.L. Leu,
        Computer Vision, Graphics, and Image Processing, vol.50,
        pp296-307 (1990)

     Heckbert, Paul S., Generic Convex Polygon Scan Conversion and Clipping,
        Graphics Gems, p. 84-86, code: p. 667-680, PolyScan/.
     Heckbert, Paul S., Concave Polygon Scan Conversion, Graphics Gems, p.
        87-91, code: p. 681-684, ConcaveScan.c.
     http://www.acm.org/tog/GraphicsGems/gems/PolyScan/
     http://www.acm.org/tog/GraphicsGems/gems/ConcaveScan.c

     For filling a region of a bitmap, see
     Heckbert, Paul S., A Seed Fill Algorithm, Graphics Gems, p. 275-277,
        code: p. 721-722, SeedFill.c. The code is at
        http://www.acm.org/tog/GraphicsGems/gems/SeedFill.c


    [Gems I]
    [Foley]
    [Hearn]

----------------------------------------------------------------------
Subject 3.04: How do I find the 'edges' in a bitmap?

    A simple method is to put the bitmap through the filter:

        -1    -1    -1
        -1     8    -1
        -1    -1    -1

    This will highlight changes in contrast.  Then any part of the
    picture where the absolute filtered value is higher than some
    threshold is an "edge".

    A more appropriate edge detector for noisy images is
    described by Van Vliet et al. "A nonlinear Laplace operator
    as edge detector in noisy images", in Computer Vision,
    Graphics, and image processing 45, pp. 167-195, 1989.


----------------------------------------------------------------------
Subject 3.05: How do I enlarge/sharpen/fuzz a bitmap?

    Sharpening of bitmaps can be done by the following algorithm:

    I_enh(x,y) = I_fuz(x,y)-k*Laplace(I_fuz(x,y))

    or in words:  An image can be sharpened by subtracting a positive
    fraction k of the Laplace from the fuzzy image.

    One "Laplace" kernel, approximating a Laplacian operator, is:
        1   1   1
        1  -8   1
        1   1   1


    The following library implements Fast Gaussian Blurs:

    MAGIC: An Object-Oriented Library for Image Analysis by David Eberly

    The library source code and the documentation (in Latex) are  at
        http://www.magic-software.com/
    The code compiles on Unix systems using g++ and on PCs using
    Microsoft Windows 3.1 and Borland C++.  The fast Gaussian blurring
    is based on a finite difference method for solving s u_s = s^2 \nabla^2 u
    where s is the standard deviation of the Gaussian (t = s^2/2).  It
    takes advantage of geometrically increasing steps in s (rather than
    linearly increasing steps in t), thus getting to a larger "time" rapidly,
    but still retaining stability.  Section 4.5 of the  documentation contains
    the algorithm description and implementation.

     A bitmap is a sampled image, a special case of a digital signal,
     and suffers from two limitations common to all digital signals.
     First, it cannot provide details at fine enough spacing to exactly
     reproduce every continuous image, nor even more detailed sampled
     images. And second, each sample approximates the infinitely fine
     variability of ideal values with a discrete set of ranges encoded
     in a small number of bits---sometimes just one bit per pixel. Most
     bitmaps have another limitation imposed: The values cannot be
     negative. The resolution limitation is especially important, but
     see "How do I display a 24 bit image in 8 bits?" for range issues.

     The ideal way to enlarge a bitmap is to work from the original
     continuous image, magnifying and resampling it. The standard way
     to do it in practice is to (conceptually) reconstruct a continuous
     image from the bitmap, and magnify and resample that instead. This
     will not give the same results, since details of the original have
     already been lost, but it is the best approach possible given an
     already sampled image. More details are provided below.

     Both sharpening and fuzzing are examples of filtering. Even more
     specifically, they can be both be accomplished with filters which
     are linear and shift invariant. A crude way to sharpen along a row
     (or column) is to set output pixel B[n] to the difference of input
     pixels, A[n]-A[n-1]. A similarly crude way to fuzz is to set B[n]
     to the average of input pixels, 1/2*A[n]+1/2*A[n-1]. In each case
     the output is a weighted sum of input pixels, a "convolution". One
     important characteristic of such filters is that a sinusoid going
     in produces a sinusoid coming out, one of the same frequency. Thus
     the Fourier transform, which decomposes a signal into sinusoids of
     various frequencies, is the key to analysis of these filters. The
     simplest (and most efficient) way to handle the two dimensions of
     images is to operate on first the rows then the columns (or vice
     versa). Fourier transforms and many filters allow this separation.

     A filter is linear if it satisfies two simple relations between the
     input and output: scaling the input by a factor scales the output
     by the same factor, and the sum of two inputs gives the sum of the
     two outputs. A filter is shift invariant if shifting the input up,
     down, left, or right merely shifts the output the same way. When a
     filter is both linear and shift invariant, it can be implemented as
     a convolution, a weighted sum. If you find the output of the filter
     when the input is a single pixel with value one in a sea of zeros,
     you will know all the weights. This output is the impulse response
     of the filter. The Fourier transform of the impulse response gives
     the frequency response of the filter. The pattern of weights read
     off from the impulse response gives the filter kernel, which will
     usually be displayed (for image filters) as a 2D stencil array, and
     it is almost always symmetric around the center. For example, the
     following filter, approximating a Laplacian (and used for detecting
     edges), is centered on the negative value.
             1/6     4/6     1/6
             4/6   -20/6     4/6
             1/6     4/6     1/6
     The symmetry allows a streamlined implementation. Suppose the input
     image is in A, and the output is to go into B. Then compute
         B[i][j] = (A[i-1][j-1]+A[i-1][j+1]+A[i+1][j-1]+A[i+1][j+1]
                    +4.0*(A[i-1][j]+A[i][j-1]+A[i][j+1]+A[i+1][j])
                    -20.0*A[i][j])/6.0

     Ideal blurring is uniform in all directions, in other words it has
     circular symmetry. Gaussian blurs are popular, but the obvious code
     is slow for wide blurs. A cheap alternative is the following filter
     (written for rows, but then applied to the columns as well).
         B[i][j] = ((A[i][j]*2+A[i][j-1]+A[i][j+1])*4
                     +A[i][j-1]+A[i][j+1]-A[i][j-3]-A[i][j+3])/16
     For sharpening, subtract the results from the original image, which
     is equivalent to using the following.
         B[i][j] = ((A[i][j]*2-A[i][j-1]-A[i][j+1])*4
                     -A[i][j-1]-A[i][j+1]+A[i][j-3]+A[i][j+3])/16
     Credit for this filter goes to Ken Turkowski and Steve Gabriel.

     Reconstruction is impossible without some assumptions, and because
     of the importance of sinusoids in filtering it is traditional to
     assume the continuous image is made of sinusoids mixed together.
     That makes more sense for sounds, where signal processing began,
     than it does for images, especially computer images of character
     shapes, sharp surface features, and halftoned shading. As pointed
     out above, often image values cannot be negative, unlike sinusoids.
     Also, real world images contain noise. The best noise suppressors
     (and edge detectors) are, ironically, nonlinear filters.

     The simplest way to double the size of an image is to use each of
     the original pixels twice in its row and in its column. For much
     better results, try this instead. Put zeros between the original
     pixels, then use the blurring filter given a moment ago. But you
     might want to divide by 8 instead of 16 (since the zeros will dim
     the image otherwise). To instead shrink the image by half (in both
     vertical and horizontal), first apply the filter (dividing by 16),
     then throw away every other pixel. Notice that there are obvious
     optimizations involving arithmetic with powers of two, zeros which
     are in known locations, and pixels which will be discarded.

----------------------------------------------------------------------
Subject 3.06: How do I map a texture on to a shape?

    Paul S. Heckbert, "Survey of Texture Mapping", IEEE Computer
    Graphics and Applications V6, #11, Nov. 1986, pp 56-67 revised
    from Graphics Interface '86 version

    Eric A. Bier and Kenneth R. Sloan, Jr., "Two-Part Texture
    Mappings", IEEE Computer Graphics and Applications V6 #9, Sept.
    1986, pp 40-53 (projection parameterizations)


----------------------------------------------------------------------
Subject 3.07: How do I detect a 'corner' in a collection of points?

    [Currently empty entry.]

----------------------------------------------------------------------
Subject 3.08: Where do I get source to display (raster font format)?

    ftp://oak.oakland.edu/SimTel/msdos/
    See also James Murray's graphics file formats FAQ:
        http://www.ora.com/centers/gff/gff-faq/index.htm

----------------------------------------------------------------------
Subject 3.09: What is morphing/how is it done?

    Morphing is the name that has come to be applied to the technique
    ILM used in the movie "Willow", where one object changes into
    another by changing both its shape and picture detail. It was a
    2D image manipulation, and has been done in different ways. The
    first method published was by Thad Beier at PDI. Michael Jackson
    famously used morphing in his music videos, notably "Black or
    White". The word is now used more generally.

    For more, see [Anderson], Chapter 3, page 59-90, and Beier's
    http://www.hammerhead.com/thad/morph.html

----------------------------------------------------------------------
Subject 3.10: How do I quickly draw a filled triangle?

    The easiest way is to render each line separately into an edge
    buffer. This buffer is a structure which looks like this (in C):

        struct { int xmin, xmax; } edgebuffer[YDIM];

    There is one entry for each scan line on the screen, and each
    entry is to be interpreted as a horizontal line to be drawn from
    xmin to xmax.

    Since most people who ask this question are trying to write fast
    games on the PC, I'll tell you where to find code.  Look at:

        ftp::/ftp.uwp.edu/pub/msdos/demos/programming/source
        ftp::/ftp.luth.se/pub/msdos/demos (Sweden)
        ftp::/NCTUCCCA.edu.tw:/PC/uwp/demos
        /www.wit.com:/mirrors/uwp/pub/msdos/demos">http://www.wit.com:/mirrors/uwp/pub/msdos/demos
        ftp::/ftp.cdrom.com:/demos

    See also Subject 3.03, which describes methods for filling polygons.

----------------------------------------------------------------------
Subject 3.11: 3D Noise functions and turbulence in Solid texturing.

    See:
        ftp://gondwana.ecr.mu.oz.au/pub/
        ftp://ftp.cis.ohio-state.edu/pub/siggraph92/siggraph92_C23.shar

    In it there are implementations of Perlin's noise and turbulence
    functions, (By the man himself) as well as Lewis' sparse
    convolution noise function (by D. Peachey) There is also some of
    other stuff in there (Musgrave's Earth texture functions, and some
    stuff on animating gases by Ebert).

    SPD (Standard Procedural Databases) package:
        ftp://avalon.chinalake.navy.mil/utils/SPD/
        ftp://avalon.chinalake.navy.mil/utils/SPD/.
        Now moved to http://www.viewpoint.com/


    References:

    [Ebert]
    Noise, Hypertexture, Antialiasing and Gesture, (Ken Perlin) in
    Chapter 6, (p.193-), The disk accompanying the book is available
    from
        ftp://archive.cs.umbc.edu/pub/.

    For more info on this text/code see:
        http://www.cs.umbc.edu/~ebert/book/book.html

    For examples from a current course based on this book, see:
        http://www.seas.gwu.edu/graphics/ProcTexCourse/
    Linke broken 21Jan03; will remove eventually if not fixed.


    [Watt:Animation]
    Three-dimensional Nocie, Chapter 7.2.1
    Simulating turbulance, Chapter 7.2.2

----------------------------------------------------------------------
Subject 3.12: How do I generate realistic sythetic textures?

    For fractal mountains, trees and sea-shells:

      SPD (Standard Procedural Databases) package:
        ftp://avalon.chinalake.navy.mil/utils/SPD/
        ftp://avalon.chinalake.navy.mil/utils/SPD/.
        Now moved to http://www.viewpoint.com/



    Reaction-Diffusion Algorithms:
      For an illustartion of the parameter space of a reaction
      diffusion system, check out the Xmorphia page at
        http://www.ccsf.caltech.edu/ismap/image.html


    References:

    [Ebert]
    Entire book devoted to this subject, with RenderMan(TM) and C code.

    [Watt:Animation]
    Procedural texture mapping and modelling, Chapter 7

    "Generating Textures on Arbitrary Surfaces Using Reaction-Diffusion"
     Greg Turk,   Computer Graphics, Vol. 25, No. 4, pp. 289-298
     July 1991 (SIGGRAPH '91)
        http://www.cs.unc.edu:80/~turk/reaction_diffusion/reaction_diffusion.html

    A list of procedural texture synthesis related web pages
         http://www.threedgraphics.com/pixelloom/tex_synth.html

----------------------------------------------------------------------
Subject 3.13: How do I convert between color models (RGB, HLS, CMYK, CIE etc)?

    References:
    [Watt:3D] pp. 313-354
    [Foley]   pp. 563-603

----------------------------------------------------------------------
Subject 3.14: How is "GIF" pronounced?
 
   "GIF" is an acronymn for "Graphics Interchange Format."  Despite the
   hard "G" in "Graphics," GIF is pronounced "JIF."  Although we don't
   have a direct quote from the official CompuServe specification
   released June 1987, here is a quote from related CompuServe documentation,
   for CompuShow, a DOS-based image viewer used shortly thereafter: 
     "The GIF (Graphics Interchange Format), pronounced "JIF", was 
      designed by CompuServe ..."
   We also have a report that the principal author of the GIF spec,
   Steve Wilhite, says "it's pronounced JIF (like the peanut butter."

   See also  
     http://www.60-seconds.com/articles/86.html
 
----------------------------------------------------------------------
Section 4. Curve Computations
----------------------------------------------------------------------
Subject 4.01: How do I generate a Bezier curve that is parallel to another Bezier?

    You can't.  The only case where this is possible is when the
    Bezier can be represented by a straight line.  And then the
    parallel 'Bezier' can also be represented by a straight line.

    The situation is different for the broader class of rational
    Bezier curves.  For example, these can represent circular arcs,
    and a parallel offset is just a concentric circular arc, also
    representable as a rational Bezier.


----------------------------------------------------------------------
Subject 4.02: How do I split a Bezier at a specific value for t?

    A Bezier curve is a parametric polynomial function from the
    interval [0..1] to a space, usually 2D or 3D.  Common Bezier
    curves use cubic polynomials, so have the form

        f(t) = a3 t^3 + a2 t^2 + a1 t + a0,

    where the coefficients are points in 3D. Blossoming converts this
    polynomial to a more helpful form.  Let s = 1-t, and think of
    tri-linear interpolation:

        F([s0,t0],[s1,t1],[s2,t2]) =
            s0(s1(s2 c30 + t2 c21) + t1(s2 c21 + t2 c12)) +
            t0(s1(s2 c21 + t2 c12) + t1(s2 c12 + t2 c03))
            =
            c30(s0 s1 s2) +
            c21(s0 s1 t2 + s0 t1 s2 + t0 s1 s2) +
            c12(s0 t1 t2 + t0 s1 t2 + t0 t1 s2) +
            c03(t0 t1 t2).

    The data points c30, c21, c12, and c03 have been used in such a
    way as to make the resulting function give the same value if any
    two arguments, say [s0,t0] and [s2,t2], are swapped. When [1-t,t]
    is used for all three arguments, the result is the cubic Bezier
    curve with those data points controlling it:

          f(t) = F([1-t,t],[1-t,t],[1-t,t])
               =  (1-t)^3 c30 +
                 3(1-t)^2 t c21 +
                 3(1-t) t^2 c12 +
                 t^3 c03.

    Notice that
           F([1,0],[1,0],[1,0]) = c30,
           F([1,0],[1,0],[0,1]) = c21,
           F([1,0],[0,1],[0,1]) = c12, _
           F([0,1],[0,1],[0,1]) = c03.

    In other words, cij is obtained by giving F argument t's i of
    which are 0 and j of which are 1. Since F is a linear polynomial
    in each argument, we can find f(t) using a series of simple steps.
    Begin with

        f000 = c30, f001 = c21, f011 = c12, f111 = c03.

    Then compute in succession:

        f00t = s f000 + t f001, f01t = s f001 + t f011,
        f11t = s f011 + t f111,
        f0tt = s f00t + t f01t, f1tt = s f01t + t f11t,
        fttt = s f0tt + t f1tt.

    This is the de Casteljau algorithm for computing f(t) = fttt.

    It also has split the curve for the intervals [0..t] and [t..1].
    The control points for the first interval are f000, f00t, f0tt,
    fttt, while those for the second interval are fttt, f1tt, f11t,
    f111.

    If you evaluate 3 F([1-t,t],[1-t,t],[-1,1]) you will get the
    derivate of f at t. Similarly, 2*3 F([1-t,t],[-1,1],[-1,1]) gives
    the second derivative of f at t, and finally using 1*2*3
    F([-1,1],[-1,1],[-1,1]) gives the third derivative.

    This procedure is easily generalized to different degrees,
    triangular patches, and B-spline curves.


----------------------------------------------------------------------
Subject 4.03: How do I find a t value at a specific point on a Bezier?

    In general, you'll need to find t closest to your search point.
    There are a number of ways you can do this. Look at [Gems I, 607],
    there's a chapter on finding the nearest point on the Bezier
    curve.  In my experience, digitizing the Bezier curve is an
    acceptable method. You can also try recursively subdividing the
    curve, see if you point is in the convex hull of the control
    points, and checking is the control points are close enough to a
    linear line segment and find the nearest point on the line
    segment, using linear interpolation and keeping track of the
    subdivision level, you'll be able to find t.


----------------------------------------------------------------------
Subject 4.04: How do I fit a Bezier curve to a circle?

    Interestingly enough, Bezier curves can approximate a circle but
    not perfectly fit a circle.
    A common approximation is to use four beziers to model a circle, each
    with control points a distance d=r*4*(sqrt(2)-1)/3 from the end points
    (where r is the circle radius), and in a direction tangent to the 
    circle at the end points.  This will ensure the mid-points of the 
    Beziers are on the circle, and that the first derivative is continuous.  
    The radial error in this approximation will be about 0.0273% of the 
    circle's radius.

    Michael Goldapp, "Approximation of circular arcs by cubic
    polynomials" Computer Aided Geometric Design (#8 1991 pp.227-238)

    Tor Dokken and Morten Daehlen, "Good Approximations of circles by
    curvature-continuous Bezier curves" Computer Aided Geometric
    Design (#7 1990 pp. 33-41).

    See also http://www.whizkidtech.net/bezier/circle/ .


----------------------------------------------------------------------
Section 5. 3D computations
----------------------------------------------------------------------
Subject 5.01: How do I rotate a 3D point?

    Let's assume you want to rotate vectors around the origin of your
    coordinate system. (If you want to rotate around some other point,
    subtract its coordinates from the point you are rotating, do the
    rotation, and then add back what you subtracted.) In 3D, you need
    not only an angle, but also an axis. (In higher dimensions it gets
    much worse, very quickly.)  Actually, you need 3 independent
    numbers, and these come in a variety of flavors.  The flavor I
    recommend is unit quaternions: 4 numbers that square and add up to
    +1.  You can write these as [(x,y,z),w], with 4 real numbers, or
    [v,w], with v, a 3D vector pointing along the axis. The concept
    of an axis is unique to 3D. It is a line through the origin
    containing all the points which do not move during the rotation.
    So we know if we are turning forwards or back, we use a vector
    pointing out along the line. Suppose you want to use unit vector u
    as your axis, and rotate by 2t degrees.  (Yes, that's twice t.)
    Make a quaternion [u sin t, cos t]. You can use the quaternion --
    call it q -- directly on a vector v with quaternion
    multiplication, q v q^-1, or just convert the quaternion to a 3x3
    matrix M. If the components of q are {(x,y,z),w], then you want
    the matrix

        M = {{1-2(yy+zz),  2(xy-wz),  2(xz+wy)},
             {  2(xy+wz),1-2(xx+zz),  2(yz-wx)},
             {  2(xz-wy),  2(yz+wx),1-2(xx+yy)}}.

    Rotations, translations, and much more are explained in all basic
    computer graphics texts.  Quaternions are covered briefly in
    [Foley], and more extensively in several Graphics Gems, and the
    SIGGRAPH 85 proceedings.

    /* The following routine converts an angle and a unit axis vector
        * to a matrix, returning the corresponding unit quaternion at no
        * extra cost. It is written in such a way as to allow both fixed
        * point and floating point versions to be created by appropriate
        * definitions of FPOINT, ANGLE, VECTOR, QUAT, MATRIX, MUL, HALF,
        * TWICE, COS, SIN, ONE, and ZERO.
        * The following is an example of floating point definitions.
        #define FPOINT double
        #define ANGLE FPOINT
        #define VECTOR QUAT
        typedef struct {FPOINT x,y,z,w;} QUAT;
        enum Indices {X,Y,Z,W};
        typedef FPOINT MATRIX[4][4];
        #define MUL(a,b) ((a)*(b))
        #define HALF(a) ((a)*0.5)
        #define TWICE(a) ((a)*2.0)
        #define COS cos
        #define SIN sin
        #define ONE 1.0
        #define ZERO 0.0
    */
    QUAT MatrixFromAxisAngle(VECTOR axis, ANGLE theta, MATRIX m)
    {
        QUAT q;
        ANGLE halfTheta = HALF(theta);
        FPOINT cosHalfTheta = COS(halfTheta);
        FPOINT sinHalfTheta = SIN(halfTheta);
        FPOINT xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
        q.x = MUL(axis.x,sinHalfTheta);
        q.y = MUL(axis.y,sinHalfTheta);
        q.z = MUL(axis.z,sinHalfTheta);
        q.w = cosHalfTheta;
        xs = TWICE(q.x);  ys = TWICE(q.y);  zs = TWICE(q.z);
        wx = MUL(q.w,xs); wy = MUL(q.w,ys); wz = MUL(q.w,zs);
        xx = MUL(q.x,xs); xy = MUL(q.x,ys); xz = MUL(q.x,zs);
        yy = MUL(q.y,ys); yz = MUL(q.y,zs); zz = MUL(q.z,zs);
        m[X][X] = ONE - (yy + zz); m[X][Y] = xy - wz; m[X][Z] = xz + wy;
        m[Y][X] = xy + wz; m[Y][Y] = ONE - (xx + zz); m[Y][Z] = yz - wx;
        m[Z][X] = xz - wy; m[Z][Y] = yz + wx; m[Z][Z] = ONE - (xx + yy);
        /* Fill in remainder of 4x4 homogeneous transform matrix. */
        m[W][X] = m[W][Y] = m[W][Z] = m[X][W] = m[Y][W] = m[Z][W] = ZERO;
        m[W][W] = ONE;
        return (q);
    }
    /* The routine just given, MatrixFromAxisAngle, performs rotation about
        * an axis passing through the origin, so only a unit vector was needed
        * in addition to the angle. To rotate about an axis not containing the
        * origin, a point on the axis is also needed, as in the following. For
        * mathematical purity, the type POINT is used, but may be defined as:
        #define POINT VECTOR
    */
    QUAT MatrixFromAnyAxisAngle(POINT o, VECTOR axis, ANGLE theta, MATRIX m)
    {
        QUAT q;
        q = MatrixFromAxisAngle(axis,theta,m);
        m[X][W] = o.x-(MUL(m[X][X],o.x)+MUL(m[X][Y],o.y)+MUL(m[X][Z],o.z));
        m[Y][W] = o.y-(MUL(m[Y][X],o.x)+MUL(m[Y][Y],o.y)+MUL(m[Y][Z],o.z));
        m[Z][W] = o.x-(MUL(m[Z][X],o.x)+MUL(m[Z][Y],o.y)+MUL(m[Z][Z],o.z));
        return (q);
    }
    /* An axis can also be specified by a pair of points, with the direction
        * along the line assumed from the ordering of the points. Although both
        * the previous routines assumed the axis vector was unit length without
        * checking, this routine must cope with a more delicate possibility. If
        * the two points are identical, or even nearly so, the axis is unknown.
        * For now the auxiliary routine which makes a unit vector ignores that.
        * It needs definitions like the following for floating point.
        #define SQRT sqrt
        #define RECIPROCAL(a) (1.0/(a))
    */
    VECTOR Normalize(VECTOR v)
    {
        VECTOR u;
        FPOINT norm = MUL(v.x,v.x)+MUL(v.y,v.y)+MUL(v.z,v.z);
        /* Better to test for (near-)zero norm before taking reciprocal. */
        FPOINT scl = RECIPROCAL(SQRT(norm));
        u.x = MUL(v.x,scl); u.y = MUL(v.y,scl); u.z = MUL(v.z,scl);
        return (u);
    }
    QUAT MatrixFromPointsAngle(POINT o, POINT p, ANGLE theta, MATRIX m)
    {
        QUAT q;
        VECTOR diff, axis;
        diff.x = p.x-o.x; diff.y = p.y-o.y; diff.z = p.z-o.z;
        axis = Normalize(diff);
        return (MatrixFromAnyAxisAngle(o,axis,theta,m));
    }

----------------------------------------------------------------------
Subject 5.02: What is ARCBALL and where is the source?

    Arcball is a general purpose 3D rotation controller described by
    Ken Shoemake in the Graphics Interface '92 Proceedings.  It
    features good behavior, easy implementation, cheap execution, and
    optional axis constraints. A Macintosh demo and electronic version
    of the original paper (Microsoft Word format) may be obtained from
    ftp::/ftp.cis.upenn.edu/pub/graphics.

    Complete source code appears in Graphics Gems IV pp. 175-192. A
    fairly complete sketch of the code appeared in the original
    article, in Graphics Interface 92 Proceedings, available from
    Morgan Kaufmann.

    The original arcball code was written for IRIS GL. A translation
    into OpenGL/GLUT, and for IRIS Performer, may be found at:
        http://cs.anu.edu.au/people/Hugh.Fisher/3dstuff/


----------------------------------------------------------------------
Subject 5.03: How do I clip a polygon against a rectangle?

    This is the Sutherland-Hodgman algorithm, an old favorite that
    should be covered in any textbook. See the selected list below.
    According to Vatti (q.v.)  "This
    [algorithm] produces degenerate edges in certain concave / self
    intersecting polygons that need to be removed as a special
    extension to the main algorithm" (though this is not a problem if
    all you are doing with the results is scan converting them.)

    It should be noted that the Sutherland-Hodgman algorithm
    may be used to clip a polygon against any convex polygon.
    Cf. also Subject 5.04.

    [Foley, van Dam]: Section 3.14.1 (pp 124 - 126)
    [Hearn]: Section 6-8, pp 237 - 242 (with actual C code!)
    See also
      http://www.csclub.uwaterloo.ca/u/mpslager/articles/sutherland/wr.html 

----------------------------------------------------------------------
|Subject 5.04: How do I clip a polygon against another polygon?

    Klamer Schutte, klamer@ph.tn.tudelft.nl has developed and implemented
    some code in C++ to perform clipping of two possibly concave 2D
    polygons. A description can be found at:
    /www.ph.tn.tudelft.nl:/People/klamer/clippoly_entry.html">http://www.ph.tn.tudelft.nl:/People/klamer/clippoly_entry.html
    To compile the source code you will need a C++ compiler with templates,
    such as g++. The source code is available at:
    ftp://ftp.ph.tn.tudelft.nl/pub/klamer/clippoly.tar.gz
|   See also http://home.attbi.com/~msleonov/pbcomp.html, which extends
    the above to permit holes.

    Alan Murta released a polygon clipper library (in C) which uses a 
    modified version of the Vatti algorithm:
      http://www.cs.man.ac.uk/aig/staff/alan/software/index.html

    References:

    Weiler, K. "Polygon Comparison Using a Graph Representation", SIGGRAPH 80
    pg. 10-18

    Vatti, Bala R. "A Generic Solution to Polygon Clipping",
    Communications of the ACM, July 1992, Vol 35, No. 7, pg. 57-63

----------------------------------------------------------------------
Subject 5.05: How do I find the intersection of a line and a plane?

    If the plane is defined as:

        a*x + b*y + c*z + d = 0

    and the line is defined as:

        x = x1 + (x2 - x1)*t = x1 + i*t
        y = y1 + (y2 - y1)*t = y1 + j*t
        z = z1 + (z2 - z1)*t = z1 + k*t

    Then just substitute these into the plane equation. You end up
    with:

        t = - (a*x1 + b*y1 + c*z1 + d)/(a*i + b*j + c*k)

    When the denominator is zero, the line is contained in the plane 
    if the numerator is also zero (the point at t=0 satisfies the
    plane equation), otherwise the line is parallel to the plane.


----------------------------------------------------------------------
Subject 5.06: How do I determine the intersection between a ray and a triangle?

    First find the intersection between the ray and the plane in which
    the triangle is situated. Then see if the point of intersection is
    inside the triangle.
    Details may be found in [O'Rourke (C)] pp.226-238, whose code is at
       http://cs.smith.edu/~orourke/ .
    Efficient code complete with statistical tests is described in the Mo:ller-
    Trumbore paper in J. Graphics Tools (C code downloadable from there):
       http://www.acm.org/jgt/papers/MollerTrumbore97/
    See also the full paper:
       http://www.Graphics.Cornell.EDU/pubs/1997/MT97.html
    See also the "3D Object Intersection" page, described in Subject 0.05.


----------------------------------------------------------------------
Subject 5.07: How do I determine the intersection between a ray and a sphere

    Given a ray defined as:

        x = x1 + (x2 - x1)*t = x1 + i*t
        y = y1 + (y2 - y1)*t = y1 + j*t
        z = z1 + (z2 - z1)*t = z1 + k*t

    and a sphere defined as:

        (x - l)**2 + (y - m)**2 + (z - n)**2 = r**2

    Substituting in gives the quadratic equation:

        a*t**2 + b*t + c = 0

    where:

        a = i**2 + j**2 + k**2
        b = 2*i*(x1 - l) + 2*j*(y1 - m) + 2*k*(z1 - n)
        c = (x1-l)**2 + (y1-m)**2 + (z1-n)**2 - r**2;

    If the discriminant of this equation is less than 0, the line does
    not intersect the sphere. If it is zero, the line is tangential to
    the sphere and if it is greater than zero it intersects at two
    points. Solving the equation and substituting the values of t into
    the ray equation will give you the points.

    Reference:
    [Glassner:RayTracing]

    See also the "3D Object Intersection" page, described in Subject 0.05.

----------------------------------------------------------------------
Subject 5.08: How do I find the intersection of a ray and a Bezier surface?

    Joy I.K. and Bhetanabhotla M.N., "Ray tracing parametric surfaces
    utilizing numeric techniques and ray coherence", Computer
    Graphics, 16, 1986, 279-286

    Joy and Bhetanabhotla is only one approach of three major method
    classes: tessellation, direct computation, and a hybrid of the
    two.  Tessellation is relatively easy (you intersect the polygons
    making up the tessellation) and has no numerical problems, but can
    be inaccurate; direct is cheap on memory, but very expensive
    computationally, and can (and usually does) suffer from precision
    problems within the root solver; hybrids try to blend the two.

    Reference:
    [Glassner:RayTracing]

    See also the "3D Object Intersection" page, described in Subject 0.05.

----------------------------------------------------------------------
Subject 5.09: How do I ray trace caustics?

    See the work of Henrik Wann Jensen at 
       http://graphics.ucsd.edu/~henrik/ 

    @inproceedings{j-rcnls-96
    , author =      "Henrik Wann Jensen"
    , title =       "Rendering Caustics on Non-Lambertian Surfaces"
    , booktitle =   "Proc. Graphics Interface '96"
    , pages =       "116--121"
    , location =    "Toronto"
    , year =         1996
    }

    Metropolis Light Transport handles this phenomenon well:
      http://www-graphics.stanford.edu/papers/metro/

    Bidirectional path tracing also handles caustics.
      http://graphics.stanford.EDU/papers/veach_thesis/ (Chapter 10)
      http://www.graphics.cornell.edu/~eric/thesis/


    Some older references:

    An expensive answer:
    @InProceedings{mitchell-1992-illumination,
      author         = "Don P. Mitchell and Pat Hanrahan",
      title          = "Illumination From Curved Reflectors",
      year           = "1992",
      month          = "July",
      volume         = "26",
      booktitle      = "Computer Graphics (SIGGRAPH '92 Proceedings)",
      pages          = "283--291",
      keywords       = "caustics, interval arithmetic, ray tracing",
      editor         = "Edwin E. Catmull",
    }

    A cheat:
    @Article{inakage-1986-caustics,
      author         = "Masa Inakage",
      title          = "Caustics and Specular Reflection Models for
                        Spherical Objects and Lenses ",
      pages          = "379--383",
      journal        = "The Visual Computer",
      volume         = "2",
      number         = "6",
      year           = "1986",
      keywords       = "ray tracing effects",
    }

    Very specialized:
    @Article{yuan-1988-gemstone,
      author         = "Ying Yuan and Tosiyasu L. Kunii and Naota
                        Inamato and Lining Sun ",
      title          = "Gemstone Fire: Adaptive Dispersive Ray Tracing
                        of Polyhedrons",
      year           = "1988",
      month          = "November",
      journal        = "The Visual Computer",
      volume         = "4",
      number         = "5",
      pages          = "259--70",
      keywords       = "caustics",
    }


----------------------------------------------------------------------
Subject 5.10: What is the marching cubes algorithm?

    The marching cubes algorithm is used in volume rendering to
    construct an isosurface from a 3D field of values.

    The 2D analog would be to take an image, and for each pixel, set
    it to black if the value is below some threshold, and set it to
    white if it's above the threshold.  Then smooth the jagged black
    outlines by skinning them with lines.

    The marching cubes algorithm tests the corner of each cube (or
    voxel) in the scalar field as being either above or below a given
    threshold.  This yields a collection of boxes with classified
    corners.  Since there are eight corners with one of two states,
    there are 256 different possible combinations for each cube.
    Then, for each cube, you replace the cube with a surface that
    meets the classification of the cube.  For example, the following
    are some 2D examples showing the cubes and their associated
    surface.

        - ----- +       - ----- -       - ----- +       - ----- +
        |:::'   |       |:::::::|       |::::   |       |   ':::|
        |:'     |       |:::::::|       |::::   |       |.    ':|
        |       |       |       |       |::::   |       |::.    |
        + ----- +       + ----- +       - ----- +       + ----- -

    The result of the marching cubes algorithm is a smooth surface
    that approximates the isosurface that is constant along a given
    threshold. This is useful for displaying a volume of oil in a
    geological volume, for example.

    References:
    "Marching Cubes: A High Resolution 3D Surface  Construction Algorithm",
    William E. Lorensen and Harvey E. Cline,
    Computer Graphics (Proceedings of  SIGGRAPH '87), Vol. 21, No. 4, pp. 163-169.

    [Watt:Animation] pp. 302-305 and 313-321
    [Schroeder]

    For alternatives to the (patented; cf. Subj. 5.11) marching cubes algorithm, 
    see
       http://www.unchainedgeometry.com/jbloom/papers/index.html
    under "Implicit Surface Polygonization."

----------------------------------------------------------------------
Subject 5.11: What is the status of the patent on the "marching cubes" algorithm?

    United States Patent Number: 4,710,876
    Date of Patent: Dec. 1, 1987
    Inventors: Harvey E. Cline, William E. Lorensen
    Assignee: General Electric Company
    Title: "System and Method for the Display of Surface Structures Contained
            Within the Interior Region of a Solid Body"
    Filed: Jun. 5, 1985
      http://www.delphion.com/
      Type in "4710876" (w/o commas, w/o quotes) into their search engine.

    United States Patent Number: 4,885,688
    Date of Patent: Dec. 5, 1989
    Inventor: Carl R. Crawford
    Assignee: General Electric Company
    Title: "Minimization of Directed Points Generated in Three-Dimensional
            Dividing Cubes Method"
    Filed: Nov. 25, 1987
      Access as above.

    For alternative, unpatented algorithms, cf. Subj. 5.10.

----------------------------------------------------------------------
Subject 5.12: How do I do a hidden surface test (backface culling) with 3D points?

    Just define all points of all polygons in clockwise order.

            c = (x3*((z1*y2)-(y1*z2))+
                (y3*((x1*z2)-(z1*x2))+
                (z3*((y1*x2)-(x1*y2))+

    x1,y1,z1, x2,y2,z2, x3,y3,z3 = the first three points of the
    polygon.

    If c is positive the polygon is visible. If c is negative the
    polygon is invisible (or the other way).


----------------------------------------------------------------------
Subject 5.13: Where can I find algorithms for 3D collision detection?

    Check out "proxima", from Purdue, which is a C++ library for 3D
    collision detection for arbitrary polyhedra.  It's a nice system;
    the algorithms are sophisticated, but the code is of modest size.

        ftp://ftp.cs.purdue.edu/pub/pse/PROX/

    For information about the I_COLLIDE 3D collision detection system
        http://www.cs.unc.edu/~geom/I_COLLIDE.html

    "Fast Collision Detection of Moving Convex Polyhedra", Rich Rabbitz,
    Graphics Gems IV, pages 83-109, includes source in C.

    SOLID: "a library for collision detection of three-dimensional
    objects undergoing rigid motion and deformation. SOLID is designed to 
    be used in interactive 3D graphics applications, and is especially 
    suited for collision detection of objects and worlds described in VRML.
    Written in standard C++, compiles under GNU g++ version 2.8.1 and 
    Visual C++ 5.0."  See:
        http://www.win.tue.nl/cs/tt/gino/solid/

    SWIFT++: a C++ library for collision detection, exact and approximate
    distance computation, and contact determination of three-dimensional
    polyhedral objects undergoing rigid motion.
    Some preliminary results indicate that it is faster than I-COLLIDE and 
    V-CLIP, and more robust than I-COLLIDE.
       http://www.cs.unc.edu/~geom/SWIFT++

    ColDet: C++ library for 3D collison detection.  Works on generic 
    polyhedra, and even polygon soups.   Uses bounding box hierarchies 
    and triangle intersection tests.   Released as open source under LGPL.
    Tested on Windows, MacOS, and Linux. http://photoneffect.com/coldet/ .

    Terdiman's lib, which might need less RAM than the above:
       http://www.codercorner.com/Opcode.htm


----------------------------------------------------------------------
Subject 5.14: How do I perform basic viewing in 3D?

    We describe the shape and position of objects using numbers,
    usually (x,y,z) coordinates. For example, the corners of a cube
    might be {(0,0,0), (1,0,0), (1,1,0), (0,1,0), (0,0,1), (1,0,1),
    (1,1,1), (0,1,1)}. A deep understanding of what we are saying with
    these numbers requires mathematical study, but I will try to keep
    this simple. At the least, we must understand that we have
    designated some point in space as the origin--coordinates
    (0,0,0)--and marked off lines in 3 mutually perpendicular
    directions using equally spaced units to give us (x,y,z) values.
    It might be helpful to know if we are using 1 to mean 1 foot, 1
    meter, or 1 parsec; the numbers alone do not tell us.

    A picture on a screen is two steps removed from the 3D world it
    depicts. First, it is a 2D projection; and second, it is a finite
    resolution approximation to the infinitely precise projection. I
    will ignore the approximation (sampling) for now. To know what the
    projection looks like, we need to know where our viewpoint is, and
    where the plane of the projection is, both in the 3D world. Think
    of it as looking out a window into a scene. As artists discovered
    some 500 years ago, each point in the world appears to be at a
    point on the window. If you move your head or look out a different
    window, everything changes. When the mathematicians understood
    what the artists were doing, they invented perspective geometry.

    If your viewpoint is at the origin--(0,0,0)--and the window sits
    parallel to the x-y plane but at z=1, projection is no more than
    (x,y,z) in the world appears at (x/z,y/z,1) on the plane. Distant
    objects will have large z values, causing them to shrink in the
    picture. That's perspective.

    The trick is to take an arbitrary viewpoint and plane, and
    transform the world so we have the simple viewing situation.
    There are two steps: move the viewpoint to the origin, then move
    the viewplane to the z=1 plane. If the viewpoint is at (vx,vy,vz),
    transform every point by the translation (x,y,z) -->
    (x-vx,y-vy,z-vz). This includes the viewpoint and the viewplane.
    Now we need to rotate so that the z axis points straight at the
    viewplane, then scale so it is 1 unit away.

    After all this, we may find ourselves looking out upside- down. It
    is traditional to specify some direction in the world or viewplane
    as "up", and rotate so the positive y axis points that way (as
    nearly as possible if it's a world vector). Finally, we have acted
    so far as if the window was the entire plane instead of a limited
    portal. A final shift and scale transforms coordinates in the
    plane to coordinates on the screen, so that a rectangular region
    of interest (our "window") in the plane fills a rectangular region
    of the screen (our "canvas" if you like).

    Details of how to define and perform the rotation of the viewplane
    have been left out, but see "How can I aim a camera in a specific
    direction?" elsewhere in this FAQ. One simple way to designate a
    plane is with the point closest to the origin, call it D. Then
    a point P is on the plane if D.P = D.D; or using d = ||D|| and
    N = D/d, if N.P = d. Aim the camera with N, and scale with d.

    A further practical difficulty is the need to clip away parts of
    the world behind us, so -(x,y,z) doesn't pop up at (x/z,y/z,1).
    (Notice the mathematics of projection alone would allow that!) In
    fact ordinarily a clipping box, the "viewing frustum", is used
    to eliminate parts of the scene outside the window left or right,
    top or bottom, and too close or too far.

    All the viewing transformations can be done using translation,
    rotation, scale, and a final perspective divide. If a 4x4
    homogeneous matrix is used, it can represent everything needed,
    which saves a lot of work. 

----------------------------------------------------------------------
Subject 5.15: How do I optimize/simplify a 3D polygon mesh?

    References:
    "Mesh Optimization" Hoppe, DeRose Duchamp, McDonald, Stuetzle,
     ACM COMPUTER GRAPHICS Proceedings, Annual Conference Series, 1993.

    "Re-Tiling Polygonal Surfaces",
     Greg Turk, ACM Computer Graphics, 26, 2, July 1992

    "Decimation of Triangle Meshes", Schroeder, Zarge, Lorensen,
    ACM Computer Graphics, 26, 2 July 1992

    "Simplification of Objects Rendered by Polygonal Approximations",
    Michael J. DeHaemer, Jr. and Michael J. Zyda, Computer & Graphics,
    Vol. 15, No. 2, 1991, Great Britain: Pergamon Press, pp. 175-184.

    "Topological Refinement Procedures for Triangular Finite Element
    Procedures", S. A. Cannan, S. N. Muthukrishnan and R. P. Phillips,
    Engineering With Computers, No. 12, p. 243-255, 1996.

    "Progressive Meshes", Hoppe, SIGGRAPH 96,
      http://research.microsoft.com/~hoppe/siggraph96pm/paper.htm
 
    Several papers by Michael Garland (quadric-based error metric):
      http://graphics.cs.uiuc.edu/~garland/

    Demos:
      By Stan Melax: http://www.cs.ualberta.ca/~melax/polychop/
      By Stefan Krause: http://www.stefan-krause.com  [Gnu Open Source]
      By "klaudius": http://www.klaudius.free.fr


----------------------------------------------------------------------
Subject 5.16: How can I perform volume rendering?

    Two principal methods can be used:
    - Ray casting or front-to-back, where the volume is behind the
      projection plane. A ray is projected from each point in the projection
      plane through the volume. The ray accumulates the properties of each
      voxel it passes through.
    - Object order or back-to-front, where the projection plane is behind
      the volume. Each slice of the volume is projected on the projection
      plane, from the farest plane to the nearest plane.

    You can also use the marching-cubes algorithm, if the extraction of
    surfaces from the data set is easy to do (see Subject 5.10).

    Here is one algorithm to do front-to-back volume rendering:

    Set up a projection plane as a plane tangent to a sphere that encloses 
    the volume. From each pixel of the projection plane, cast a ray 
    through the volume by using a Bresenham 3D algorithm.
    The ray accumulates properties from each voxel intersected, stopping
    when the ray exits the volume. The pixel value on
    the projection plane determines the final color of the ray.

    For unshaded images (i.e., without gradient and light computations),
    if 	C  is the ray color            t  the ray transparency
        C' the new ray color           t' the new ray transparency
        Cv the voxel color             tv the voxel transparency
    then:
        C' = C + t*Cv       and        t' = t * tv
    with initial values: C = 0.0 and t = 1.0

    An alternate version: instead of C' = C + t*Cv , use :
        C' = C + t*Cv*(1-tv)^p     with p a float variable.
    Sometimes this gives the best results.
    When the ray has accumulated transparency, if it becomes negligible
    (e.g., t<0.1), the process can stop and proceed to the next ray.

    References:

    Bresenham 3D:
      - http://www.sct.gu.edu.au/~anthony/info/graphics/bresenham.procs
      - [Gems IV] p. 366
    Volume rendering:
      - [Watt:Animation] pp. 297-321
      - IEEE Computer Graphics and application
        Vol. 10, Nb. 2, March 1990 - pp. 24-53
      - "Volume Visualization"
        Arie Kaufman - Ed. IEEE Computer Society Press Tutorial
      - "Efficient Ray Tracing of Volume Data"
        Marc Levoy - ACM Transactions on Graphics, Vol. 9, Nb 3, July 1990

----------------------------------------------------------------------
Subject 5.17: Where can I get the spline description of the famous teapot etc.?

    See the Standard Procedural Databases software, whose official
    distribution site is 
        http://www.acm.org/tog/resources/SPD/
    This database contains much useful 3D code, including spline surface
    tessellation, for the teapot.

----------------------------------------------------------------------
Subject 5.18: How can the distance between two lines in space be computed?

    Let x_i be points on the respective lines and n_i unit direction         
    vectors along the lines.  Then the distance is
       | (x_1 - x_0)^T (n_1 X n_0) | / || n_1 X n_0 ||.
    Often one wants the points of closest approach as well as the distance.
    The following is robust C code from Seth Teller that computes the 
    these points on two 3D lines.  It also classifies 
    the lines as parallel, intersecting, or (the generic case) skew.
    What's listed below shows the main ideas; the full code is at
      http://graphics.lcs.mit.edu/~seth/geomlib/linelinecp.c

    // computes pB ON line B closest to line A
    // computes pA ON line A closest to line B
    // return: 0 if parallel; 1 if coincident; 2 if generic (i.e., skew)
    int
    line_line_closest_points3d (
        POINT *pA, POINT *pB,			// computed points
        const POINT *a, const VECTOR *adir,		// line A, point-normal form
        const POINT *b, const VECTOR *bdir )	// line B, point-normal form
    {
    static VECTOR Cdir, *cdir = &Cdir;
    static PLANE Ac, *ac = &Ac, Bc, *bc = &Bc;
    
        // connecting line is perpendicular to both
        vcross ( cdir, adir, bdir );
    
        // check for near-parallel lines
        if ( !vnorm( cdir ) )   {
            *pA = *a;	// all points are closest
            *pB = *b;
            return 0;	// degenerate: lines parallel
            }
    
        // form plane containing line A, parallel to cdir
        plane_from_two_vectors_and_point ( ac, cdir, adir, a );
    
        // form plane containing line B, parallel to cdir
        plane_from_two_vectors_and_point ( bc, cdir, bdir, b );
    
        // closest point on A is line A ^ bc
        intersect_line_plane ( pA, a, adir, bc );
    
        // closest point on B is line B ^ ac
        intersect_line_plane ( pB, b, bdir, ac );
    
        // distinguish intersecting, skew lines
        if ( edist( pA, pB ) < 1.0E-5F )
            return 1;     // coincident: lines intersect
        else
            return 2;     // distinct: lines skew
    }

    Also Dave Eberly has code for computing distance between various 
    geometric primitives, including MinLineLine(), at
      http://www.magic-software.com


----------------------------------------------------------------------
Subject 5.19: How can I compute the volume of a polyhedron?

    Assume that the surface is closed, every face is a triangle, and
    the vertices of each triangle are oriented ccw from the outside.
    Let Volume(t,p) be the signed volume of the tetrahedron formed
    by a point p and a triangle t.  This may be computed by a 4x4
    determinant, as in [O'Rourke (C), p.26].
            Choose an arbitrary point p (e.g., the origin), and compute
    the sum Volume(t_i,p) for every triangle t_i of the surface.  That
    is the volume of the object.  The justification for this claim
    is nontrivial, but is essentially the same as the justification for
    the computation of the area of a polygon (Subject 2.01).

    C Code available at http://cs.smith.edu/~orourke/ 
    and http://www.acm.org/jgt/papers/Mirtich96/ .

    For computing the volumes of n-d convex polytopes, 
    there is a C implementation by Bueeler and Enge of various
    algorithms available at

    http://www.Mathpool.Uni-Augsburg.DE/~enge/Volumen.html .

----------------------------------------------------------------------
Subject 5.20:  How can I decompose a polyhedron into convex pieces?
 
    Usually this problem is interpreted as seeking a collection
    of pairwise disjoint convex polyhedra whose set union is the
    original polyhedron P.  The following facts are known about
    this difficult problem:
 
       o  Not every polyhedron may be partitioned by diagonals into
          tetrahedra.  A counterexample is due to Scho:nhardt
          [O'Rourke (A), p.254].
 
       o  Determining whether a polyhedron may be so partitioned is
          NP-hard, a result due to Seidel & Ruppert [Disc. Comput. Geom. 
          7(3) 227-254 (1992).]
 
       o  Removing the restriction to diagonals, i.e., permitting
          so-called Steiner points, there are polyhedra of n vertices
          that require n^2 convex pieces in any decomposition.
          This was established by Chazelle [SIAM J. Comput. 
          13: 488-507 (1984)]. See also [O'Rourke (A), p.256]
 
       o  An algorithm of Palios & Chazelle guarantees at most
          O(n+r^2) pieces, where r is the number of reflex edges
          (i.e., grooves). [Disc. Comput. Geom. 5:505-526 (1990).]
 
       o  Barry Joe's geompack package, at 
             ftp://ftp.cs.ualberta.ca/pub/geompack,
          includes a 3D convex decomposition Fortran program. 
 
       o  There seems to be no other publicly available code.

----------------------------------------------------------------------
Subject 5.21: How can the circumsphere of a tetrahedron be computed?


    Let a, b, c, and d be the corners of the tetrahedron, with
    ax, ay, and az the components of a, and likewise for b, c, and d.  
    Let |a| denote the Euclidean norm of a, and let a x b denote the 
    cross product of a and b.  Then the center m and radius r of the
    circumsphere are given by
    
       |                                                                       |
       | |d-a|^2 [(b-a)x(c-a)] + |c-a|^2 [(d-a)x(b-a)] + |b-a|^2 [(c-a)x(d-a)] |
       |                                                                       |
    r= -------------------------------------------------------------------------
                                 | bx-ax  by-ay  bz-az |
                               2 | cx-ax  cy-ay  cz-az |
                                 | dx-ax  dy-ay  dz-az |
   
    and
   
           |d-a|^2 [(b-a)x(c-a)] + |c-a|^2 [(d-a)x(b-a)] + |b-a|^2 [(c-a)x(d-a)]
    m= a + ---------------------------------------------------------------------
                                   | bx-ax  by-ay  bz-az |
                                 2 | cx-ax  cy-ay  cz-az |
                                   | dx-ax  dy-ay  dz-az |
    
    Some notes on stability:
    
    - Note that the expression for r is purely a function of differences between
      coordinates.  The advantage is that the relative error incurred in the
      computation of r is also a function of the _differences_ between the
      vertices, and is not influenced by the _absolute_ coordinates of the
      vertices.  In most applications, vertices are usually nearer to each other
      than to the origin, so this property is advantageous.
    
      Similarly, the formula for m incurs roundoff error proportional to the
      differences between vertices, but not proportional to the absolute 
      coordinates of the vertices until the final addition.
    
    - These expressions are unstable in only one case:  if the denominator is
      close to zero.  This instability, which arises if the tetrahedron is 
      nearly degenerate, is unavoidable.  Depending on your application, you 
      may want to use exact arithmetic to compute the value of the determinant.
      See
        http://www.geom.umn.edu/software/cglist/alg.html
      or
        http://www.cs.cmu.edu/~quake/robust.html

----------------------------------------------------------------------
Subject 5.22: How do I determine if two triangles in 3D intersect?

    Let the two triangles be T1 and T2.  If T1 lies strictly to one side 
    of the plane containing T2, or T2 lies strictly to one side of the 
    plane containing T1, the triangles do not intersect.  Otherwise,
    compute the line of intersection L between the planes.  Let Ik
    be the interval (Tk inter L), k=1,2.  Either interval may be empty.
    T1 and T2 intersect iff I1 and I2 overlap.

    This method is decribed in Tomas Mo:ller, "A fast triangle-triangle
    intersection test," J. Graphics Tools 2(2) 25-30 1997.  C code at
    http://www.acm.org/jgt/papers/Moller97/ .  See also
    http://www.ce.chalmers.se/staff/tomasm/code/ 
    http://www.magic-software.com/MgcIntersection.html

    See also the "3D Object Intersection" page, described in Subject 0.05.

    NASA's "Intersect" code will intersect any number of triangulated
    surfaces provided that each of the surfaces is both closed and manifold.
      http://www.nas.nasa.gov/~aftosmis/cart3d/surfaceModeling.html#AuxProgs
    Based on "Robust and Efficient Cartesian Mesh Generation for 
    Component-Based Geometry" AIAA Paper 97-0196. Michael Aftosmis.

----------------------------------------------------------------------
Subject 5.23:  How can a 3D surface be reconstructed from a collection of points?

    This is a difficult problem.  There are two main variants: 
    (1) when the points are organized into parallel slices through 
    the object; (2) when the points are unorganized.  
    For (1), see this survey:
       D. Meyers, S. Skinner, K. Sloan. "Surfaces from Contours"
       ACM Trans. Graph. 11(3) Jul 1992, 228--258.
       http://www.acm.org/pubs/citations/journals/tog/1992-11-3/p228-meyers/
    Code (NUAGES) is available at 
       http://www-sop.inria.fr/prisme/logiciel/nuages.html.en
       ftp://ftp-sop.inria.fr/prisme/NUAGES/Nuages/NUAGES_SRC.tar.gz
    For (2), see this paper:
       H. Hoppe, T. DeRose, T. Duchamp, J. McDonald, W. Stuetzle
       "Surface reconstruction from unorganized points"
       Proc. SIGGRAPH '92, 71--78.
    and P. Kumar's collection of links at
       http://members.tripod.com/~GeomWiz/www.sites.html
    New code, Cocone, written with CGAL, based on recent work by 
    N. Amenta, S. Choi, T. K. Dey and N. Leekha:
       http://www.cis.ohio-state.edu/~tamaldey/cocone.html

----------------------------------------------------------------------
Subject 5.24: How can I find the smallest sphere enclosing a set of points in 3D? 

    Although not obvious, the smallest sphere enclosing a set of points
    in any dimension can be found by Linear Programming.  This was proved
    by Emo Welzl in the paper, "Smallest enclosing disks (balls and 
    ellipsoids)" [Lecture Notes Comput. Sci., 555, Springer-Verlag, 1991, 
    359--370].  +   Code developed by Bernd Gaertner available (GNU 
    General Public License) at:
        http://www.inf.ethz.ch/~gaertner/miniball.html
    This code is remarkably efficient: e.g., 2 seconds for 10^6 points in 
    3D on an Ultra-Sparc II.  See also Dave Eberly's direct implementation
    of Welzl's algorithm:
        http://www.magic-software.com/MgcContainment3D.html

----------------------------------------------------------------------
Subject 5.25: What's the big deal with quaternions?

    This could mean "Why do they evoke such heated debate?" or "What are
    their virtues?"

    The heat of debate is hard to explain, but it's been happening for many
    decades. When Gibbs first deprecated the quaternion product and split it
    into a cross product and a dot product, one outraged Victorian called
    the result a "hermaphrodite monster" -- and that before the Internet's
    flame wars. Generally, the quaternion advocates seem to feel the
    opponents are lazy or thick-headed, and that deeper understanding of
    quaternions would lead to deeper appreciation. The opponents don't
    appreciate that attitude, and seem to feel the advocates are snooty or
    sheep, and that matrices and such are less abstract and do just fine.
    (Advocates of Clifford algebra would claim that both sides are mired in
    the past.) Passion aside, quaternions have appropriate uses, as do their
    alternatives.

    Someone new to the debate first needs to know what quaternions are, and
    what they're supposed to be good for. Quaternions are a quadruple of
    numbers, used to represent 3D rotations.
        q = [x,y,z,w] = [(x,y,z),w] = [V,w]

    The "norm" of a quaternion N(q) is conventionally the sum of the squares
    of the four components. Some writers confuse this with the magnitude,
    which is the square root of the norm. Another common misconception is
    that only quaternions of unit norm can be used, those with the sum of
    the four squares equal to 1, but that is wrong (though they are
    preferred).
        [U sin a,cos a] rotates by angle 2a around unit vector U

    Popular non-quaternion options are 3x3 special orthogonal matrices (9
    numbers with constraints), Euler angles (3 numbers), axis-angle (4
    numbers), and angular velocity vectors (3 numbers). None of these
    options actually _are_ rotations, which are physical; they _represent_
    rotations. The distinction is important because, for example, it is
    common to use an axis-angle with an angle greater than 360 degrees to
    tell an animation system to spin an object more than a full turn,
    something a matrix cannot say. In mathematics, the usual meaning of a
    rotation would not allow the multiple spin version, which can lead to
    confusing debates.
        q and -q represent the same rotation

    Two rotations, the physical things, can be applied one after the other.
    Assuming the two rotation axes have a least one point in common, the
    result will be another rotation. Some rotation representations handle
    this gracefully, some don't. For quaternions and matrices, forms of
    multiplication are defined such that the product gives the desired
    result. For Euler angles especially there is no simple computation.
        q = q2 q1 = [V2,w2][V1,w1] = [V2xV1+w2V1+w1V2,w2w1-V2.V1]

    Every rotation has a reverse rotation, such that the combination of the
    two leaves an object as it was. (Rotations are an algebraic "group".)
    Euler angles make reversals difficult to compute. Other representations,
    including quaternions, make them simple.
        reverse([V,w]) = [V,-w]
        q^(-1) = [-V,w]/(V.V+ww)

    Two physical rotations are also more or less similar. Unit quaternions
    do a particularly good job of representing similar rotations with
    similar numbers.
        similar(q1,q2) = |q1.q2| = | x1x2+y1y2+z1z2+w1w2 |

    Points in space, the physical things, are normally represented as 3 or 4
    numbers. The effect of a rotation on a collection of points can be
    computed from the representation of the rotation, and here matrices seem
    fastest, using three dot products. Using their own product twice,
    quaternions are a bit less efficient. (They are usually converted to
    matrices at the last minute.)
        p2 = q p1 q^(-1)

    Sequences of rotations can be interpolated, so that the object being
    turned is rotated to specific poses at specific times. This motivated
    Ken Shoemake's early use of quaternions in computer graphics, as
    published in 1985. He used an analog of linear interpolation (sometimes
    called "lerp") that he called "Slerp", and also introduced an analog of
    a piecewise Bezier curve. A few years later in some course notes he
    described another curve variation he called "Squad", which still seems
    to be popular. Later authors have proposed many alternatives.
                            sin (1-t)A      sin tA
        Slerp(q1,q2;t) = q1 ---------- + q2 ------, cos A = q1.q2
                               sin A         sin A

        Squad(q1,a1,b2,q2;t) = Slerp(Slerp(q1,q2;t),
                                     Slerp(a1,b2;t);
                                     2t(1-t))

    Physics simulation, aerospace control, and robotics are examples of
    computations which also depend on rotation representation. Constrained
    rotations like a wheel on an axle or the elbow bend of a robot typically
    use specialized representations, such as an angle alone. In many general
    situations, however, quaternions have proved valuable.
        2 dq = W q dt, W is the angular velocity vector

    User interfaces for 3D rotation also require a representation. Direct
    manipulation interfaces typically use angles for jointed figures, but
    for freer manipulation may use quaternions, as in Arcball or
    through-the-lens camera control. As Shoemake's _full_ Graphics Gems code
    for Arcball demonstrates (with the [CAPS LOCK] key), any rotation can be
    graphed as an arc on a sphere. (Not to be confused with the quaternion
    unit sphere in 4D.) Whether quaternions, or any other representation,
    are helpful for numeric presentation and input seems a matter of taste
    and circumstance.
        q = U2 U1^(-1) = [U1xU2,U1.U2]

    Because of their metric properties for representing rotations, unit
    quaternions are most common. Advocates frequently point out that it is
    far cheaper to normalize the length of a non-zero quaternion than to
    bring a matrix back to rotation form. Also Shoemake's later conversion
    code cheaply creates a correct rotation matrix from _any_ quaternion
    (found with his Euler angle code from Graphics Gems, which does the same
    for all 24 variations of that representation).
        Normalize(q) = q/Sqrt(q.q)

    Comparisons to Euler angles may mention "gimbal lock" (frequently
    misspelled) as a disadvantage quaternions avoid. In the physical world
    where gyroscopes are mounted on nested pivots, which are called gimbals,
    locking is a real problem quaternions cannot help. What's usually meant
    is that because the similarity of rotations organizes them somewhat like
    a sphere, while similarity of vectors is quite different, an inevitable
    misfit plagues Euler angles. This can show up in behavior much like
    physical gimbal lock, but also in other ways. The difficulties are
    topological, and aiming runs into them as well, even if quaternions are
    used. Quaternion authors who propose using curves in the vector space of
    quaternion logarithms often risk the misfit unawares. Frankly, you must
    pick through the literature carefully, whether informal and online or
    refereed and printed, because mistakes are tragically common.

    To explore Graphics Gems code, see "Where is all the source?" in this
    FAQ. To read more about quaternions, you have many options. Since they
    were discovered in 1843 by Hamilton (the same Irish mathematician and
    physicist whose name shows up in quantum mechanics), quaternions have
    found many friends, as a web search will reveal. Quaternions can be
    approached and applied in numerous different ways, so if you keep
    looking it's likely you will find something that suits your taste and
    your needs.

      (Subject 0.04) [Eberly], Ch. 2.
      http://www.maths.tcd.ie/pub/HistMath/People/Hamilton/OnQuat/
        Hamilton's original paper. Not easy for today's readers.
      K. Shoemake. Animating Rotation with Quaternion Curves.
      Proceedings of Siggraph 85.
        Original animation method. Covers all the basics.
      ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/
        Later Shoemake tutorial. More complete than most authors.
      Graphics Gems I-V, various authors, various articles.
        As usual, a helpful source of code and discussion.
      ftp://ftp.netcom.com/pub/hb/hbaker/quaternion/
        Henry Baker collects good quaternion stuff. Access spotty.
      http://linux.rice.edu/~rahul/hbaker/quaternion/
        Henry Baker collection with more reliable access.
      http://www.eecs.wsu.edu/~hart/papers/vqr.pdf
        Visualizing quaternion rotation. May help build intuition.
      http://graphics.stanford.edu/courses/cs348c-95-fall
      /software/quatdemo/
        The GL code implementing above Hart et al. paper.
      http://www.diku.dk/students/myth/quat.html
        Mathematical, but not too fast and not too fancy.
      http://www.cs.berkeley.edu/~laura/cs184/quat/quaternion.html
        Laura Downs covers the fundamentals.
      http://graphics.cs.ucdavis.edu/GraphicsNotes/Quaternions
      /Quaternions.htm
        Ken Joy covers the fundamentals.
      http://www.gg.caltech.edu/STC/rr_sig97.html
        High-tech interpolation method. Demanding but rewarding.
      Duff, Tom: Quaternion Splines for Animating Orientation,
      Proceedings of the USENIX Association Second Computer Graphics
      Workshop (held in Monterey, CA 12-13 Dec. 1985), pp. 54-62.
        Subdivision paper in odd place. Author last seen at Pixar.

----------------------------------------------------------------------
Subject 5.26:  How can I aim a camera in a specific direction?

    What's needed is a method for creating a rotation that turns one unit
    vector to line up with another. To aim at an object, you can subtract
    the position of the camera from the position of the object to get a
    vector which you then normalize. The vector you want to turn is the
    camera forward vector, commonly a unit vector along the camera -z axis.
    Be warned that more than one rotation can achieve aim alone. (The issue
    is rather complicated, as laid out in Ken Shoemake's article on twist
    reduction in Graphics Gems IV.) For example, even if the camera is
    already properly aimed you could rotate it around its z axis. The most
    direct rotation is given by the non-unit quaternion
        q = [(b,-a,0),1-c], to aim -z axis along unit vector (a,b,c)
    Normalization is advised, but it will fail for aim vector (0,0,1). In
    that case just rotate 180 degrees around the y axis, using
        q = [(0,1,0),0]

    If the camera is level after rotation by quaternion [(x,y,z),w], the y
    component of its rotated x axis will be zero, so
        xy+wz = 0
    If it is upright, the y component of its rotated y axis will not be
    negative, so
        ww-xx+yy-zz >= 0

    To ensure these two desirable properties, aim with a more sophisticated
    non-unit quaternion
        [(bs,-at,ab),st], where s = r-c, t = r+1, and r = sqrt(aa+cc).
    This can also fail to normalize, in which case normalize instead
        [(0,1+c,-b),0]
    Unless the aim vector is null, this will succeed. If the aim vector has
    not been normalized and its magnitude is m = sqrt(aa+bb+cc), substitute
    1->m. That is, use t = r+m and use m+c.

    More generally, to rotate unit vector U1 directly to unit vector U2, the
    non-unit quaternion will be
        q = [U1xU2,1+U1.U2]

    Why? If U is a unit vector, then it is normal to a plane through the
    origin with equation U.P = 0. Reflection in that plane is given by
    reversing the U component of P.
        reflect(P,U) = P ^ 2(U.P)U
    The quaternion product of U1 and U2 is [U1xU2,-U1.U2], so
        -2 (U.P) = PU + UP
    Noting UU = -1, this gives a quaternion reflection formula.
        reflect(P,U) = P + (PU+UP)U
                     = P ^ P + UPU
                     = UPU
    Reflecting with U1 then U2, by U2(U1 P U1)U2, rotates by twice the angle
    between the planes, with axis perpendicular to both normals. Noting U1U2
    is the conjugate of U2U1, and -q rotates like q, the rotation quaternion
    is
        q = -U2U1 = -[U2xU1,-U2.U1] = [U1xU2,U1.U2]
    This q fails to aim U1 at U2 by rotating twice as much as needed, but
    its square root succeeds. One square root of unit q is 1+q normalized,
    geometrically the bisection of the great arc from the identity to q.
    There is an inevitable singularity when U2 is the opposite of U1,
    because any perpendicular axis gives an equally direct 180 degree
    rotation.

    [These quaternion methods were provided by Ken Shoemake.]

----------------------------------------------------------------------
Subject 5.27: How do I transform normals?

    In 3D, the orientation of a plane in space can be given by a
    vector perpendicular to the plane, a "normal vector" or "normal"
    for short. Often it is convenient to keep that vector of unit
    length, or "normalized"; be careful of the different meanings
    of "normality". A smooth surface has a plane tangent to each
    point, and by extension a normal to that plane is called a
    "surface normal". Graphics code also cheats by associating
    artificial normal vectors with the vertices of polygonal models
    to simulate the reflection properties of curved surfaces;
    these are called "vertex normals".
    
    The "orientation" of a plane has two meanings, both of which
    usually apply. Aside from the rotational tilting and turning
    meaning, there is also the sense of "side". A closed convex
    surface made of polygons has two sides, an inside and an
    outside, and normals can be assigned to the polygons in such
    a way that they all consistently point outside. This is
    often desirable for shading and culling.
    
    When a model is defined in one coordinate system and used in
    another, as is commonly done, it may be necessary to transform
    normals also. If the change of point coordinates is effected
    by means of a rotation plus a translation, one simply rotates
    the normals as well (with no translation). Other coordinate
    changes need more care.
    
    Although it is possible to use projective transformations to
    map a model into world coordinates, ordinarily they are used
    only for viewing. It is usually a mistake to apply perspective
    to a normal, as shading and culling are best done in world
    coordinates for correct results. Also perspective may be
    computed using degenerate matrices which are not invertible,
    though that need not be the case. For the importance of this,
    see below.
    
    The combination of a linear transformation and a translation
    is called an affine transformation, and is performed as a
    matrix multiplication plus a vector addition:
      p' = A(p) = Lp + t.
    When the model-to-world point transform is affine, the proper
    way to transform normals is with the transpose of the inverse
    of L.
      n' = (L^{-1})^T n
    However that is not enough.
    
    If L includes scaling effects, a unit normal in model space
    will usually transform to a non-unit normal, which can cause
    problems for shaders and other code. This may need correcting
    after the normal is transformed.
    
    If L includes reflection, the inside-outside orientation of
    the normal is reversed. This, too, can cause problems, and
    may need correcting. The determinant of L will be negative
    in this case.
    
    When a complicated distortion is used, it must be approximated
    differently at each point in space by a linear transform made
    up of partial derivatives, the Jacobian. The matrix for the
    Jacobian replaces L in the equation for transforming normals.
    
    Why use the transposed inverse?
    Write the dot product of column vectors n and v as a matrix
    product n^T v. Write vector v as a difference of points, q-p.
    Let p, q, and thus v lie in the desired plane, and let n be
    normal to it. Vectors at right angles have zero dot product.
      n^T v = 0
    The transform v' of v is
      v' = (Lq+t)-(Lp+t)
         = (Lq-Lp)+(t-t)
         = L(q-p)
         = Lv
    The transform n' of n will remain normal if it satisfies
      n'^T v' = n^T v
    Let n' = Mn for some M. Then the requirement is
      n'^T v' = (Mn)^T (Lv)
              = n^T (M^T L) v
              = n^T v
    This holds if
      M^T L = I
    where I is the identity. Right multiplying by the inverse
    L^{-1} and transposing both sides gives, as claimed,
      M = (L^{-1})^T
    When L is a rotation, L^{-1} = L^T, so M = L. When L has no
    inverse it will still have an "adjoint" to substitute for
    for orthogonality purposes, differing only by a scale factor.

----------------------------------------------------------------------
Section 6. Geometric Structures and Mathematics
----------------------------------------------------------------------
Subject 6.01: Where can I get source for Voronoi/Delaunay triangulation?

    For 2-d Delaunay triangulation, try Shewchuk's triangle program.  It
    includes options for constrained triangulation and quality mesh
    generation.  It uses exact arithmetic.

    The Delaunay triangulation is equivalent to computing the convex hull
    of the points lifted to a paraboloid.  For n-d Delaunay triangulation
    try Clarkson's hull program (exact arithmetic) or Barber and Huhdanpaa's
    Qhull program (floating point arithmetic).  The hull program also
    computes Voronoi volumes and alpha shapes.  The Qhull program also
    computes 2-d Voronoi diagrams and n-d Voronoi vertices.  The output of
    both programs may be visualized with Geomview.

    There are many other codes for Delaunay triangulation and Voronoi
    diagrams.  See Amenta's list of computational geometry software.
    Especially noteworthy is the CGAL code: Subject 0.07 and
    http://www.cgal.org.

    The Delaunay triangulation satisfies the following property: the
    circumcircle of each triangle is empty.  The Voronoi diagram is the
    closest-point map, i.e., each Voronoi cell identifies the points that
    are closest to an input site.  The Voronoi diagram is the dual of
    the Delaunay triangulation.  Both structures are defined for general
    dimension.  Delaunay triangulation is an important part of mesh
    generation.

    There is a FAQ of polyhedral computation explaining how to compute
    n-d Delaunay triangulation and n-d Voronoi diagram using a convex hull
    code, and how to use the linear programming technique to 
    determine the Voronoi cells adjacent to a given Voronoi cell
    efficiently for large scale or higher dimensional cases.

    Avis' lrs code uses the same file formats as cdd. It
    uses exact arithmetic and is useful
    for problems with very large output size, since it does not
    require storing the output.

    On a closely related topic, see
      http://www.cis.ohio-state.edu/~tamaldey/medialaxis.htm
    for computation of the 3D medial axis from the Voronoi diagram.


    References:

    Amenta:   http://www.geom.umn.edu/software/cglist

    Avis:     ftp://mutt.cs.mcgill.ca/pub/C/lrs.html

    Barber &  http://www.geom.umn.edu/locate/qhull
    Huhdanpaa ftp://geom.umn.edu/pub/software/
              ftp://ftp.geom.umn.edu/pub/software/

    Clarkson: http://cm.bell-labs.com/netlib/voronoi/hull.html
              ftp://cm.bell-labs.com/netlib/voronoi/hull.shar.Z

    Geomview: http://www.geom.umn.edu/locate/geomview
              ftp://geom.umn.edu/pub/software/geomview/

    Polyhedral Computation FAQ:
              http://www.ifor.math.ethz.ch/ifor/staff/fukuda/fukuda.html

    Shewchuk: http://www.cs.cmu.edu/~quake/triangle.html
              ftp://cm.bell-labs.com/netlib/voronoi/triangle.shar.Z


    [O' Rourke (C)] pp. 168-204

    [Preparata & Shamos] pp. 204-225

    Chew, L. P. 1987. "Constrained Delaunay Triangulations," Proc. Third
    Annual ACM Symposium on Computational Geometry.

    Chew, L. P. 1989. "Constrained Delaunay Triangulations," Algorithmica
    4:97-108. (UPDATED VERSION OF CHEW 1987.)

    Fang, T-P. and L. A. Piegl. 1994. "Algorithm for Constrained Delaunay
    Triangulation," The Visual Computer 10:255-265. (RECOMMENDED!)

    Frey, W. H. 1987. "Selective Refinement: A New Strategy for Automatic
    Node Placement in Graded Triangular Meshes," International Journal for
    Numerical Methods in Engineering 24:2183-2200.

    Guibas, L. and J. Stolfi. 1985. "Primitives for the Manipulation of
    General Subdivisions and the Computation of Voronoi Diagrams," ACM
    Transactions on Graphics 4(2):74-123.

    Karasick, M., D. Lieber, and L. R. Nackman. 1991. "Efficient Delaunay
    Triangulation Using Rational Arithmetic," ACM Transactions on Graphics
    10(1):71-91.

    Lischinski, D. 1994. "Incremental Delaunay Triangulation," Graphics
    Gems IV, P. S. Heckbert, Ed. Cambridge, MA: Academic Press Professional.
    (INCLUDES C++ SOURCE CODE -- THANK YOU, DANI!)

    [Okabe]

    Schuierer, S. 1989. "Delaunay Triangulation and the Radiosity
    Approach," Proc. Eurographics '89, W. Hansmann, F. R. A. Hopgood, and
    W. Strasser, Eds. Elsevier Science Publishers, 345-353.

    Subramanian, G., V. V. S. Raveendra, and M. G. Kamath. 1994. "Robust
    Boundary Triangulation and Delaunay Triangulation of Arbitrary
    Triangular Domains," International Journal for Numerical Methods in
    Engineering 37(10):1779-1789.

    Watson, D. F. and G. M. Philip. 1984. "Survey: Systematic
    Triangulations," Computer Vision, Graphics, and Image Processing
    26:217-223.

----------------------------------------------------------------------
Subject 6.02: Where do I get source for convex hull?

    For n-d convex hulls, try Clarkson's hull program (exact arithmetic)
    or Barber and Huhdanpaa's Qhull program (floating point arithmetic).
    Qhull 3.1 includes triangulated output and improved
    handling of difficult inputs.   Qhull computes convex hulls,
    Delaunay triangulations, Voronoi diagrams, and halfspace
    intersections about a point.

    Qhull handles numeric precision problems by merging facets. The output
    of both programs may be visualized with Geomview.

    In higher dimensions, the number of facets may be much smaller than
    the number of lower-dimensional features.  When this is the case,
    Fukuda's cdd program is much faster than Qhull or hull.

    There are many other codes for convex hulls.  See Amenta's list of
    computational geometry software.

    References:

    Amenta:   http://www.geom.umn.edu/software/cglist/

    Barber &  http://www.geom.umn.edu/locate/qhull
    Huhdanpaa 

    Clarkson: http://cm.bell-labs.com/netlib/voronoi/hull.html
              ftp://cm.bell-labs.com/netlib/voronoi/hull.shar.Z

    Geomview: http://www.geom.umn.edu/locate/geomview
              ftp://geom.umn.edu/pub/software/geomview/

    Fukuda:   http://www.ifor.math.ethz.ch/staff/fukuda/cdd_home/cdd.html
              ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/


    [O' Rourke (C)] pp. 70-167
    C code for Graham's algorithm on p.80-96.
    Three-dimensional convex hull discussed in Chapter 4 (p.113-67).
    C code for the incremental algorithm on p.130-60.

    [Preparata & Shamos] pp. 95-184


----------------------------------------------------------------------
Subject 6.03: Where do I get source for halfspace intersection?

    For n-d halfspace intersection, try Fukuda's cdd program or Barber
    and Huhdanpaa's Qhull program.  Both use floating point arithmetic.
    Fukuda includes code for exact arithmetic.  Qhull handles numeric
    precision problems by merging facets.

    Qhull computes halfspace intersection by computing a convex hull.
    The intersection of halfspaces about the origin is equivalent to the
    convex hull of the halfspace coefficients divided by their offsets.
    See Subject 6.02 for more information.

    References:

    Barber &  http://www.geom.umn.edu/locate/qhull
    Huhdanpaa 

    Fukuda:   ftp://ifor13.ethz.ch/pub/fukuda/cdd/

    [Preparata & Shamos] pp. 315-320



----------------------------------------------------------------------
Subject 6.04: What are barycentric coordinates?
 
    	Let p1, p2, p3 be the three vertices (corners) of a closed 
    triangle T (in 2D or 3D or any dimension).  Let t1, t2, t3 be real 
    numbers that sum to 1, with each between 0 and 1:  t1 + t2 + t3 = 1,
    0 <= ti <= 1.  Then the point p = t1*p1 + t2*p2 + t3*p3 lies in
    the plane of T and is inside T.  The numbers (t1,t2,t3) are called the
    barycentric coordinates of p with respect to T. They uniquely identify
    p.  They can be viewed as masses placed at the vertices whose
    center of gravity is p.
    	For example, let p1=(0,0), p2=(1,0), p3=(3,2).  The
    barycentric coordinates (1/2,0,1/2) specify the point
    p = (0,0)/2 + 0*(1,0) + (3,2)/2 = (3/2,1), the midpoint of the p1-p3 
    edge.
    	If p is joined to the three vertices, T is partitioned
    into three triangles.  Call them T1, T2, T3, with Ti not incident
    to pi.  The areas of these triangles Ti are proportional to the
    barycentric coordinates ti of p.  
    
    Reference:
    [Coxeter, Intro. to Geometry, p.217].

----------------------------------------------------------------------
Subject 6.05: How can I generate a random point inside a triangle?

    	Use barycentric coordinates (see item 53) .  Let A, B, C be the
    three vertices of your triangle.  Any point P inside can be expressed
    uniquely as P = aA + bB + cC, where a+b+c=1 and a,b,c are each >= 0.
    Knowing a and b permits you to calculate c=1-a-b.  So if you can
    generate two random numbers a and b, each in [0,1], such that
    their sum <=1, you've got a random point in your triangle.
    	Generate random a and b independently and uniformly in [0,1] 
    (just divide the standard C rand() by its max value to get such a 
    random number.) If a+b>1, replace a by 1-a, b by 1-b.  Let c=1-a-b.  
    Then aA + bB + cC is uniformly distributed in triangle ABC: the reflection
    step a=1-a; b=1-b gives a point (a,b) uniformly distributed in the triangle
    (0,0)(1,0)(0,1), which is then mapped affinely to ABC.
    Now you have barycentric coordinates a,b,c.  Compute your point 
    P = aA + bB + cC.

    Reference: [Gems I], Turk, pp. 24-28, contains a similar but different
               method which requires a square root.

----------------------------------------------------------------------
Subject 6.06: How do I evenly distribute N points on (tesselate) a sphere?
    
    "Evenly distributed" doesn't have a single definition.  There is a
    sense in which only the five Platonic solids achieve regular
    tesselations, as they are the only ones whose faces are regular
    and equal, with each vertex incident to the same number of faces.
    But generally "even distribution" focusses not so much on the
    induced tesselation, as it does on the distances and arrangement
    of the points/vertices.  For example, eight points can be placed
    on the sphere further away from one another than is achieved by
    the vertices of an inscribed cube: start with an inscribed cube,
    twist the top face 45 degrees about the north pole, and then
    move the top and bottom points along the surface towards the equator 
    a bit.

    The various definitions of "evenly distributed" lead into moderately 
    complex mathematics. This topic happens to be a FAQ on sci.math as well 
    as on comp.graphics.algorithms; a much more extensive and rigorous 
    discussion written by Dave Rusin can be found at:
    http://www.math.niu.edu/~rusin/known-math/95/sphere.faq

    A simple method of tesselating the sphere is repeated subdivision. An
    example starts with a unit octahedron. At each stage, every triangle in
    the tesselation is divided into 4 smaller triangles by creating 3 new
    vertices halfway along the edges. The new vertices are normalized,
    "pushing" them out to lie on the sphere. After N steps of subdivision,
    there will be 8 * 4^N triangles in the tesselation.

    A simple example of tesselation by subdivision is available at
       ftp://ftp.cs.unc.edu/pub/users/jon/sphere.c

    One frequently used definition of "evenness" is a distribution that 
    minimizes a 1/r potential energy function of all the points, so that in 
    a global sense points are as "far away" from each other as possible. 
    Starting from an arbitrary distribution, we can either use numerical 
    minimization algorithms or point repulsion, in which all the points 
    are considered to repel each other according to a 1/r^2 force law and 
    dynamics are simulated. The algorithm is run until some convergence 
    criterion is satisfied, and the resulting distribution is our approximation.
    
    Jon Leech developed code to do just this.  It is available at
    ftp://ftp.cs.unc.edu/pub/users/jon/points.tar.gz.
    See his README file for more information.  His distribution includes
    sample output files for various n < 300, which may be used off-the-shelf
    if that is all you need.

    Another method that is simpler than the above, but attains less
    uniformity, is based on spacing the points along a spiral that
    encircles the sphere.
    Code available from links at http://cs.smith.edu/~orourke/.

----------------------------------------------------------------------
Subject 6.07: What are coordinates for the vertices of an icosohedron?

    Data on various polyhedra is available at
    http://cm.bell-labs.com/netlib/polyhedra/index.html, or
    http://netlib.bell-labs.com/netlib/polyhedra/index.html, or
    http://www.netlib.org/polyhedra/index.html
    For the icosahedron, the twelve vertices are:
 
      (+- 1, 0, +-t), (0, +-t, +-1), and (+-t, +-1, 0)
 
    where t = (sqrt(5)-1)/2, the golden ratio.
    Reference: "Beyond the Third Dimension" by Banchoff, p.168.
    
    
----------------------------------------------------------------------
Subject 6.08: How do I generate random points on the surface of a sphere?

    There are several methods.  Perhaps the easiest to understand is
    the "rejection method":  generate random points in an origin-
    centered cube with opposite corners (r,r,r) and (-r,-r,-r).
    Reject any point p that falls outside of the sphere of radius r.
    Scale the vector to lie on the surface.  Because the cube to sphere
    volume ratio is pi/6, the average number of iterations before an
    acceptable vector is found is 6/pi = 1.90986.  This essentially
    doubles the effort, and makes this method slower than the "trig
    method."  A timing comparison conducted by Ken Sloan showed that
    the trig method runs in about 2/3's the time of the rejection method.
    He found that methods based on the use of normal distributions are
    twice as slow as the rejection method.

    The trig method.  This method works only in 3-space, but it is
    very fast.  It depends on the slightly counterintuitive fact (see
    proof below) that each of the three coordinates is uniformly
    distributed on [-1,1] (but the three are not independent,
    obviously).  Therefore, it suffices to choose one axis (Z, say)
    and generate a uniformly distributed value on that axis.  This
    constrains the chosen point to lie on a circle parallel to the
    X-Y plane, and the obvious trig method may be used to obtain the
    remaining coordinates.
    
    	(a) Choose z uniformly distributed in [-1,1].
    	(b) Choose t uniformly distributed on [0, 2*pi).
    	(c) Let r = sqrt(1-z^2).
    	(d) Let x = r * cos(t).
    	(e) Let y = r * sin(t).
    
    This method uses uniform deviates (faster to generate than normal
    deviates), and no set of coordinates is ever rejected.  
    
    Here is a proof of correctness for the fact that the z-coordinate is
    uniformly distributed.  The proof also works for the x- and y-
    coordinates, but note that this works only in 3-space.
    
    The area of a surface of revolution in 3-space is given by
    
    	A = 2 * pi * int_a^b f(x) * sqrt(1 + [f'(x}]^2) dx
    
    Consider a zone of a sphere of radius R.  Since we are integrating in
    the z direction, we have
    
    	f(z) = sqrt(R^2 - z^2)
    	f'(z) = -z / sqrt(R^2-z^2)
    
    	1 + [f'(z)]^2 = r^2 / (R^2-z^2)
    
    	A = 2 * pi * int_a^b sqrt(R^2-z^2) * R/sqrt(R^2-z^2) dz
    	  = 2 * pi * R int_a^b dz
    	  = 2 * pi * R * (b-a)
    	  = 2 * pi * R * h, 
    	  
    where h = b-a is the vertical height of the zone.  Notice how the integrand
    reduces to a constant.  The density is therefore uniform.

    Here is simple C code implementing the trig method:
    
    void SpherePoints(int n, double X[], double Y[], double Z[])
    {
      int i;
      double x, y, z, w, t;
    
      for( i=0; i< n; i++ ) {
        z = 2.0 * drand48() - 1.0;
        t = 2.0 * M_PI * drand48();
        w = sqrt( 1 - z*z );
        x = w * cos( t );
        y = w * sin( t );
        printf("i=%d:  x,y,z=\t%10.5lf\t%10.5lf\t%10.5lf\n", i, x,y,z);
        X[i] = x; Y[i] = y; Z[i] = z;
      }
    }
   
    A complete package is available at
    ftp://cs.smith.edu/pub/code/sphere.tar.gz (4K),
    reachable from http://cs.smith.edu/~orourke/ .

    If one wants to generate the random points in terms of longitude
    and latitude in degrees, these equations suffice:
      Longitude = random * 360 - 180
      Latitude  = [arccos( random * 2 - 1 )/pi ] * 180 - 90


    References:
    [Knuth, vol. 2]
    [Graphics Gems IV] "Uniform Random Rotations"

----------------------------------------------------------------------
Subject 6.09: What are Plucker coordinates?

    A common convention is to write umlauted u as "ue", so you'll also see
    "Pluecker". Lines in 3D can easily be given by listing the coordinates of
    two distinct points, for a total of six numbers. Or, they can be given as
    the coordinates of two distinct planes, eight numbers. What's wrong with
    these? Nothing; but we can do better. Pluecker coordinates are, in a sense,
    halfway between these extremes, and can trivially generate either. Neither
    extreme is as efficient as Pluecker coordinates for computations.

    When Pluecker coordinates generalize to Grassmann coordinates, as laid
    out beautifully in [Hodge], Chapter VII, the determinant definition
    is clearly the one to use. But 3D lines can use a simpler definition.
    Take two distinct points on a line, say

        P = (Px,Py,Pz)
        Q = (Qx,Qy,Qz)

    Think of these as vectors from the origin, if you like. The Pluecker
    coordinates for the line are essentially

        U = P - Q
        V = P x Q

    Except for a scale factor, which we ignore, U and V do not depend on the
    specific P and Q! Cross products are perpendicular to their factors, so we
    always have U.V = 0. In [Stolfi] lines have orientation, so are the same
    only if their Pluecker coordinates are related by a positive scale factor.

    As determinants of homogeneous coordinates, begin with the 4x2 matrix

        [ Px  Qx ] row x
        [ Py  Qy ] row y
        [ Pz  Qz ] row z
        [  1   1 ] row w

    Define Pluecker coordinate Gij as the determinant of rows i and j, in that
    order. Notice that Giw = Pi - Qi, which is Ui. Now let (i,j,k) be a cyclic
    permutation of (x,y,z), namely (x,y,z) or (y,z,x) or (z,x,y), and notice
    that Gij = Vk. Determinants are anti-symmetric in the rows, so Gij = -Gji.
    Thus all possible Pluecker line coordinates are either zero (if i=j) or
    components of U or V, perhaps with a sign change. Taking the w component
    of a vector as 0, the determinant form will operate just as well on a
    point P and vector U as on two points. We can also begin with a 2x4 matrix
    whose rows are the coefficients of homogeneous plane equations, E.P=0,
    from which come dual coordinates G'ij. Now if (h,i,j,k) is an even
    permutation of (x,y,z,w), then Ghi = G'jk. (Just swap U and V!)

    Got Pluecker, want points? No problem. At least one component of U is
    non-zero, say Ui, which is Giw. Create homogeneous points Pj = Gjw + Gij,
    and Qj = Gij. (Don't expect the P and Q that we started with, and don't
    expect w=1.) Want plane equations? Let (i,j,k,w) be an even permutation of
    (x,y,z,w), so G'jk = Giw. Then create Eh = G'hk, and Fh = G'jh.

    Example: Begin with P = (2,4,8) and Q = (2,3,5). Then U = (0,1,3) and
    V = (-4,6,-2). The direct determinant forms are Gxw=0, Gyw=1, Gzw=3,
    Gyz=-4, Gzx=6, Gxy=-2, and the dual forms are G'yz=0, G'zx=1, G'xy=3,
    G'xw=-4, G'yw=6, G'zw=-2. Take Uz = Gzw = G'xy = 3 as a suitable non-zero
    element. Then two planes meeting in the line are

        (G'xy  G'yy  G'zy  G'wy).P = 0
        (G'xx  G'xy  G'xz  G'xw).P = 0

    That is, a point P is on the line if it satisfies both these equations:

        3 Px + 0 Py + 0 Pz - 6 Pw = 0
        0 Px + 3 Py - 1 Pz - 4 Pw = 0

    We can also easily determine if two lines meet, or if not, how they pass.
    If U1 and V1 are the coordinates of line 1, U2 and V2, of line 2, we look
    at the sign of U1.V2 + V1.U2. If it's zero, they meet. The determinant form
    reveals even permutations of (x,y,z,w):
        G1xw G2yz + G1yw G2zx + G1zw G2xy + G1yz G2xw + G1zx p2yw + G1xy p2zw

    Two oriented lines L1 and L2 can interact in three different ways:
    L1 might intersect L2, L1 might go clockwise around L2, or L1 might go
    counterclockwise around L2. Here are some examples:

    	     | L2            | L2            | L2
    	L1   |          L1   |          L1   |
    	-----+----->    ----------->    -----|----->
    	     |               |               |
             V               V               V
    	 intersect    counterclockwise   clockwise
    	     | L2            | L2            | L2
    	L1   |          L1   |          L1   |
    	<----+-----     <----|------    <-----------
    	     |               |               |
             V               V               V

    The first and second rows are just different views of the same lines,
    once from the "front" and once from the "back." Here's what they might
    look like if you look straight down line L2 (shown here as a dot).

    	L1                               ---------->
    	-----o---->     L1   o           L1   o
    	                ---------->
    	 intersect    counterclockwise    clockwise


    The Pluecker coordinates of L1 and L2 give you a quick way to test
    which of the three it is.

    	cw:   U1.V2 + V1.U2 < 0
    	ccw:  U1.V2 + V1.U2 > 0
    	thru: U1.V2 + V1.U2 = 0

    So why is this useful? Suppose you want to test if a ray intersects
    a triangle in 3-space. One way to do this is to represent the ray and
    the edges of the triangle with Pluecker coordinates. The ray hits the
    triangle if and only if it hits one of the triangle's edges, or it's
    "clockwise" from all three edges, or it's "counterclockwise" from all
    three edges. For example...

          o  _
          | |\      		...in this picture, the ray
    	  |   \			is oriented counterclockwise
    	------ \ -->		from all three edges, so it
    	  |     \ 		must intersect the triangle.
    	  v      \
    	  o-----> o

    Using Pluecker coordinates, ray shooting tests like this take only
    a few lines of code.

    Grassmann coordinates allow similar methods to be used for points,
    lines, planes, and so on, and in a space of any dimension. In the
    case of lines in 2D, only three coordinates are required:

        Gxw = Px-Qx     = -G'y
        Gyw = Py-Qy     =  G'x
        Gxy = PxQy-PyQx =  G'w

    Since P and Q are distinct, Giw is non-zero for i = x or y. Then

        (Gix,Giy,Giw) is a point P1 on L
        (Gxw,Gyw,Gww)+P1 is a point P2 on L
        (G'x,G'y,G'w).P = 0 is an equation for L

    Two lines in a 2D perspective plane always meet, perhaps in an
    ideal point (meaning they're parallel in ordinary 2D). Calling
    their homogeneous point of intersection P, the computation from
    Grassmann coordinates nicely illustrates the convenience. (See
    Subj 1.03, "How do I find intersections of 2 2D line segments?")
    For i = x,y,w, set

        Pi = G'j H'k ^ G'k H'j, where (i,j,k) is even

    See [Hodge] for a thorough discussion of the theory, [Stolfi] for
    a little theory with a concise implementation for low dimensions
    (see Subj. 0.04), and these articles for further discussion:
      J. Erickson, Pluecker Coordinates, Ray Tracing News 10(3) 1997,
      http://www.acm.org/tog/resources/RTNews/html/rtnv10n3.html.

      Ken Shoemake, Pluecker Coordinate Tutorial,
      Ray Tracing News 11(1) 1998,
      http://www.acm.org/tog/resources/RTNews/html/rtnv11n1.html.


----------------------------------------------------------------------
Section 7. Contributors
----------------------------------------------------------------------
Subject 7.01: How can you contribute to this FAQ?

    Send email to orourke@cs.smith.edu with your suggestions, possible
    topics, corrections, or pointers to information.  

----------------------------------------------------------------------
Subject 7.02: Contributors.  Who made this all possible.

    [All email addresses now removed to protect the authors from spam.]
    Jens Alfke 
    Nina Amenta 
    Leen Ammeraal 
    Scott Anguish 
    Ian Ashdown 
    Barak 
    Brad Barber 
    James Beech 
    David Bouman 
    Paul Bourke 
    Lars Brinkhoff 
    Andrew Bromage 
    Brent Burley 
    R. Kevin Burton 
    Gene Caldwell 
    Ken Clarkson 
    Robert Day 
    Tamal Dey 
    Martin Dillon 
    Thomas Djafari 
    Dave Eberly 
    John Eickemeyer 
    John E (Edward) Ellis 
    Jeff Erickson 
    Ata Etemadi 
    Hugh Fisher 
    David N. Fogel 
    Arne K. Frick 
    Olexandr Frantchuk 
    Robert W. Fuentes 
    Komei Fukuda 
    William Gibbons 
    Normand Grgoire 
    Eric Haines 
    Jeff Hameluck 
    Sandy Harris 
    Luiz Henrique de Figueiredo 
    Steve Hollasch 
    Bill Jones 
    Richard Kinch 
    Craig Kolb 
    Uffe Kousgaard 
    Stefan Krause 
    Piyush Kumar 
    Steve Lamont 
    Ben Landon 
    Erik Larsen 
    Jon Leech 
    Michael V. Leonov 
    Sum Lin 
    Alan J. Livingston 
    Sebastien Loisel 
    Fritz Lott 
    Jacob Marner 
    Marc Christopher Martin 
    John McNamara 
    Samuel Murphy 
    Alan Murta 
    S. N. Muthukrishnan 
    Andrew Myers 
    David Nixon 
    Aaron Orenstein 
    Joseph O'Rourke 
    Samuel S. Paik 
    Leonidas Palios 
    Amitha Perera 
    Brian Peters 
    Lavoie Philippe 
    Christopher Phillips 
    Tom Plunket 
    Aaron Quigley 
    Rudi Bjxrn Rasmussen 
    Greg Roelofs 
    Christian von Roques 
    Dave Seaman 
    Jonathan R. Shewchuk 
    Rainer Michael Schmid 
    Klamer Schutte 
    Andrzej Serafin 
    ZhengYu Shan 
    James Sharman 
    Ken Shoemake 
    Jeff Somers 
    Jon Stone 
    Dan Sunday 
    Seth Teller 
    Saurabh Tendulkar 
    Yael "YoeL" Touboul 
    Anson Tsao 
    Bob van Manen 
    Remco Veltkamp 
    Jim Ward 
    Jason Weiler 
    Karsten Weiss 
    Stefan Wolfrum 
    Daniel S. Zwick 

    Previous Editors:
    Jon Stone 
    Anson Tsao 



#include "arithmetic_coder.h"

#include <assert.h>
#include <string.h>

/*
  This is an implementation of a "range coder".  Whereas the usual
  implementation of an arithmetic coder outputs 1 bit at a time, the
  range coder presented here outputs a byte at a time.  This translates
  into some potential CPU time savings, which can be important in a 
  server environment where you're encoding messages for many clients.
  Also, it makes for slightly simpler code, which I like.
*/


// NUM_HIGH_BITS is how many bits we shift out at a time (1 byte).
const int NUM_HIGH_BITS = 8;

// NUM_LOW_BITS is the machine word size, minus 1, minus the number of
// high bits.  The -1 happens because we need to represent numbers from
// 0 to 2**n, not just 0 to 2**n-1.  So the high bit is almost entirely
// unused, but not quite.  We could actually work around this, by making
// the code more complicated; in return we'd get 1 extra bit of precision
// in the math.  But since this is sample code, I have elected not to
// do that.
const int NUM_LOW_BITS = 31 - NUM_HIGH_BITS;


// If the range of the coding interval is less than RANGE_TOO_LOW, it's
// time to shift a byte into the output.  This gives us back some precision.
const unsigned int RANGE_TOO_LOW = (1 << NUM_LOW_BITS);


// We start out with the maximum range, since that means maximal math precision.
const unsigned long RANGE_INITIAL = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);
const unsigned int OVERFLOW_MASK = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);

void Arithmetic_Encoder::reset() {
    low = 0;
    range = RANGE_INITIAL;
    num_bytes_output = 0;
}

Arithmetic_Encoder::Arithmetic_Encoder() {
    reset();
}


// has_anything_been_packed() checks to see if we are still satisfying
// the initial conditions set by reset().  If so, nobody ever put anything
// into this coder.  (I use this in networking situations, where I run
// through a bunch of code that might pack data or might not; then at the
// end I check whether there's actually anything to send).
bool Arithmetic_Encoder::has_anything_been_packed() {
    if (low != 0) return true;
    if (range != RANGE_INITIAL) return true;
    if (num_bytes_output != 0) return true;

    return false;
}


// renormalize() is the routine that maintains math precision.  It
// checks to see whether 'range' is too low; if so, it shifts some
// data into the output, then scales up the coding interval.
void Arithmetic_Encoder::renormalize() {
    while (range <= RANGE_TOO_LOW) {
        assert((range >> NUM_LOW_BITS) <= 1);
        assert(range > 0);
        unsigned int output = low >> NUM_LOW_BITS;
        output_byte(output);
        range <<= 8;
        low <<= 8;
        low &= (OVERFLOW_MASK - 1);
    }
}


// output_byte() puts a byte into the output buffer.  Normally
// you'd expect the parameter to be between 0 and 255; however,
// we allow it to have an extra overflow bit on top, so that it
// can be as big as 511.  If it's got an overflow bit, we perform
// a carry into earlier data.  Putting the overflow checking
// here simplifies the rest of the code.
void Arithmetic_Encoder::output_byte(unsigned int value) {
    assert(value < 512);

    if (value >= 256) {
        carry();
        value -= 256;
    }

    assert(value < 256);
    assert(num_bytes_output < AC_MAX_BUFFER_LEN);
    output_bytes[num_bytes_output++] = value;
}


// When it's time to carry, it means we need to add 1 to the
// most recent byte we had output.  Usually that is all we
// need to do; but if that byte is already 255, the carry
// will make it 0, and create another carry bit, which
// we need to propagate one byte earlier in the output. 
// You might imagine this continuing for many output bytes,
// but such a circumstance would be extremely rare.

// This carry stuff is necessary because to maintain precision
// we need to output results whenever the range becomes small;
// but if the range happens to straddle 0.5, then we don't
// know whether the most significant bit will end up being
// 1 or 0.  But we need to shift it out anyway.  The carry
// mechanism is just a way of fixing that when we resolve
// which side of 0.5 we are on.
void Arithmetic_Encoder::carry() {
    int cursor = num_bytes_output;

    while (--cursor >= 0) {
        unsigned int value = output_bytes[cursor];
        if (value == 255) {
            output_bytes[cursor] = 0;
        } else {
            output_bytes[cursor] = value + 1;
            break;
        }
    }
}


// When it's time to put a new value into the encoder, we call pack().
void Arithmetic_Encoder::pack(Symbol_Count *symbol, Data_Model_1D *model) {
    unsigned long numerator = symbol->numerator;
    assert(numerator != 0);

    renormalize();

    // To get the new offset, multiply 'range' by the fraction for
    // the left-hand side of this symbol's probability interval.
    // This fraction is (symbol->base_numerator / (1 << model->denominator_bits)).
    // A slight rearrangement gives the expression below.
    unsigned int offset = (range >> model->denominator_bits) * symbol->base_numerator;

    // Move the low end of the interval by this offset.
    unsigned int old_low = low;
    low += offset;
    assert(low >= old_low);  // Don't overflow out of machine word!

    // Shrink the range by the factor (numerator / model->denominator_bits).
    range >>= model->denominator_bits;
    range *= numerator;
}

// This is the all-equal-probability version of 'pack' (as seen in part 1!)
void Arithmetic_Encoder::pack(int value, int limit) {
    assert(value >= 0);
    assert(value < limit);

    renormalize();

    range /= limit;
    unsigned int old_low = low;
    low += value * range;
    assert(low >= old_low);  // Don't overflow out of machine word!
}


void Arithmetic_Encoder::flush() {
    // This seems tricky, but hey... we want to not output
    // more information than we need, which means we need to output
    // enough bits to yield a number n, where low <= n <= high.
    // The most economical way to do this is output the MSB's of
    // (low + range - 1) until we output a bit that differs from 'low'.

    // But since we're outputting whole bytes at a time here, we want
    // to detect a byte that differs from 'low'.  This is the same as
    // saying, output up to and including the first byte for which
    // (range - 1) is nonzero.  The renormalize() call ensures that that
    // byte becomes the top byte.  Then we just output that top byte.
    // Unless of course 'low' is 0, in which case we get something
    // >= low just by doing nothing.

    // Khalid Sayood's book "Introduction to Data Compression, 2nd Edition" 
    // gives  an expression for computing how many bits you need ideally
    // (section 4.4.1).
    // But it's hard to implement this expression in a robust way,
    // and it also doesn't account for the inherent leakage due to
    // fixed precision math.  Thus our method here.

    renormalize();
    if (low == 0) return;

    unsigned int high = low + range - 1;

    output_byte(high >> NUM_LOW_BITS);
    assert((high >> NUM_LOW_BITS) > (low >> NUM_LOW_BITS));
}


// get_result() is just a wrapper to give us our buffer.
void Arithmetic_Encoder::get_result(unsigned char **data_return, int *length_return) {
    flush();

    *data_return = output_bytes;
    *length_return = num_bytes_output;
}




//
// That's all for the encoder!  Now comes the decoder.
//

void Arithmetic_Decoder::reset() {
    low = 0;
    code = 0;
    range = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);

    input_byte_cursor = 0;
}

Arithmetic_Decoder::Arithmetic_Decoder() {
    reset();
}

Arithmetic_Decoder::~Arithmetic_Decoder() {
}


//
// Much like the Encoder's version of renormalize, we are just trying
// to duplicate the action of the encoder here.
//
void Arithmetic_Decoder::renormalize() {
    while (range <= RANGE_TOO_LOW) {
        assert((range >> NUM_LOW_BITS) <= 1);
        assert(range > 0);
        range <<= 8;
        low <<= 8;
        code <<= 8;
        low &= (OVERFLOW_MASK - 1);

        code &= (OVERFLOW_MASK - 1);
        if (code < low) {
            code |= OVERFLOW_MASK;  // Riddle me this.
        }

        code |= input_next_byte();
    }
}

// input_next_byte() pulls the next byte out of the buffer and
// hands it to us.  This code looks more complicated than it
// ought to be; the reason is that we're shifting in 8 bits
// at a time, but those 8 bits don't land exactly on a byte
// boundary.  They're shifted by a bit, as a consequence of the
// fact that our 'range' is only 31 bits.  We might shrink
// 'range' down to 24 bits for the decoder here, but that would
// cause the math to come out differently than on the encoder,
// which ruins the situation.
//
// The modification mentioned earlier that allows 'range' to be
// 32 bits in both the encoder and the decoder would solve this
// problem.
int Arithmetic_Decoder::input_next_byte() {
    int first_part, second_part;
    if ((input_byte_cursor == 0) || (input_byte_cursor > num_input_bytes)) {
        first_part = 0;
    } else {
        assert(input_byte_cursor - 1 < num_input_bytes) ;
        first_part = input_bytes[input_byte_cursor - 1] & 1;
    }

    if (input_byte_cursor >= num_input_bytes) {
        second_part = 0;
    } else {
        second_part = input_bytes[input_byte_cursor] & ~1;
    }

    // @Robustness: This assertion is loose; should figure out exactly
    // what it ought to be.
    assert(input_byte_cursor <= num_input_bytes + 5);

    input_byte_cursor++;
    return (first_part << 7) + (second_part >> 1);
}

// @Speed: find_value is a lot slower than it needs to be,
// because it was written to be simple.
//
// The goal of this function is just to find the correct symbol
// whose probability interval contains the current code value.
// For simplicity we search linearly.  To gain speed, we can do
// a binary search, or something more sophisticated.
unsigned long find_value(Data_Model_1D *model,
                         unsigned long point, unsigned long range) {
    int i;
    for (i = 0; i < model->num_symbols; i++) {
        unsigned long divided = range >> model->denominator_bits;
        unsigned long d0 = divided * model->symbols[i].base_numerator;
        unsigned long d1 = divided * (model->symbols[i].base_numerator + model->symbols[i].numerator);

        if (point >= d1) continue;
        if (point < d0) continue;

        return i;
    }

    assert(0);
    return model->num_symbols - 1;
}

// unpack() is just the entry point that gives us back a value.
unsigned long Arithmetic_Decoder::unpack(Data_Model_1D *model) {
    renormalize();

    // For an explnation of the math here, see Arithmetic_Coder::pack.
    unsigned long value = find_value(model, code - low, range);

    unsigned int offset = (range >> model->denominator_bits) * model->symbols[value].base_numerator;

    unsigned int old_low = low;
    low += offset;
    assert(low >= old_low);  // Don't overflow out of machine word!

    int numerator = model->symbols[value].numerator;

    range >>= model->denominator_bits;
    range *= numerator;

    return value;
}

// This is the all-equal-probability version of 'unpack' (as seen in part 1!)
unsigned long Arithmetic_Decoder::unpack(unsigned long limit) {
    assert(limit >= 1);

    renormalize();

    range /= limit;
    unsigned long value = (code - low) / range;
    assert(value < (unsigned long) limit);
    low += value * range;

    return value;
}


// set_data() is called with the data to decode, when we want to
// start decoding.  We copy the data into an internal buffer, and
// then we also shift the first 4 bytes of that buffer into the
// variable 'code' which represents the part of the number we
// are actively decoding.
void Arithmetic_Decoder::set_data(unsigned char *data, int length) {
    assert(length < AC_MAX_BUFFER_LEN);
    memcpy(input_bytes, data, length);
    num_input_bytes = length;

    int i;
    for (i = 0; i < 4; i++) {
        code <<= 8;
        code |= input_next_byte();
    }
}

// might_there_be_any_data_left() is another function I use to
// help me out when dealing with garbage packets; I wouldn't
// worry about it too much!
bool Arithmetic_Decoder::might_there_be_any_data_left() {
    if (input_byte_cursor < num_input_bytes + 4) return true;
    return false;
}

int Arithmetic_Encoder::get_maximum_data_length() {
    return num_bytes_output + 4;
}
#include "arithmetic_coder.h"

#include <assert.h>
#include <string.h>

/*
  This is an implementation of a "range coder".  Whereas the usual
  implementation of an arithmetic coder outputs 1 bit at a time, the
  range coder presented here outputs a byte at a time.  This translates
  into some potential CPU time savings, which can be important in a 
  server environment where you're encoding messages for many clients.
  Also, it makes for slightly simpler code, which I like.
*/


// NUM_HIGH_BITS is how many bits we shift out at a time (1 byte).
const int NUM_HIGH_BITS = 8;

// NUM_LOW_BITS is the machine word size, minus 1, minus the number of
// high bits.  The -1 happens because we need to represent numbers from
// 0 to 2**n, not just 0 to 2**n-1.  So the high bit is almost entirely
// unused, but not quite.  We could actually work around this, by making
// the code more complicated; in return we'd get 1 extra bit of precision
// in the math.  But since this is sample code, I have elected not to
// do that.
const int NUM_LOW_BITS = 31 - NUM_HIGH_BITS;


// If the range of the coding interval is less than RANGE_TOO_LOW, it's
// time to shift a byte into the output.  This gives us back some precision.
const unsigned int RANGE_TOO_LOW = (1 << NUM_LOW_BITS);


// We start out with the maximum range, since that means maximal math precision.
const unsigned long RANGE_INITIAL = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);
const unsigned int OVERFLOW_MASK = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);

void Arithmetic_Encoder::reset() {
    low = 0;
    range = RANGE_INITIAL;
    num_bytes_output = 0;
}

Arithmetic_Encoder::Arithmetic_Encoder() {
    reset();
}


// has_anything_been_packed() checks to see if we are still satisfying
// the initial conditions set by reset().  If so, nobody ever put anything
// into this coder.  (I use this in networking situations, where I run
// through a bunch of code that might pack data or might not; then at the
// end I check whether there's actually anything to send).
bool Arithmetic_Encoder::has_anything_been_packed() {
    if (low != 0) return true;
    if (range != RANGE_INITIAL) return true;
    if (num_bytes_output != 0) return true;

    return false;
}


// renormalize() is the routine that maintains math precision.  It
// checks to see whether 'range' is too low; if so, it shifts some
// data into the output, then scales up the coding interval.
void Arithmetic_Encoder::renormalize() {
    while (range <= RANGE_TOO_LOW) {
        assert((range >> NUM_LOW_BITS) <= 1);
        assert(range > 0);
        unsigned int output = low >> NUM_LOW_BITS;
        output_byte(output);
        range <<= 8;
        low <<= 8;
        low &= (OVERFLOW_MASK - 1);
    }
}


// output_byte() puts a byte into the output buffer.  Normally
// you'd expect the parameter to be between 0 and 255; however,
// we allow it to have an extra overflow bit on top, so that it
// can be as big as 511.  If it's got an overflow bit, we perform
// a carry into earlier data.  Putting the overflow checking
// here simplifies the rest of the code.
void Arithmetic_Encoder::output_byte(unsigned int value) {
    assert(value < 512);

    if (value >= 256) {
        carry();
        value -= 256;
    }

    assert(value < 256);
    assert(num_bytes_output < AC_MAX_BUFFER_LEN);
    output_bytes[num_bytes_output++] = value;
}


// When it's time to carry, it means we need to add 1 to the
// most recent byte we had output.  Usually that is all we
// need to do; but if that byte is already 255, the carry
// will make it 0, and create another carry bit, which
// we need to propagate one byte earlier in the output. 
// You might imagine this continuing for many output bytes,
// but such a circumstance would be extremely rare.

// This carry stuff is necessary because to maintain precision
// we need to output results whenever the range becomes small;
// but if the range happens to straddle 0.5, then we don't
// know whether the most significant bit will end up being
// 1 or 0.  But we need to shift it out anyway.  The carry
// mechanism is just a way of fixing that when we resolve
// which side of 0.5 we are on.
void Arithmetic_Encoder::carry() {
    int cursor = num_bytes_output;

    while (--cursor >= 0) {
        unsigned int value = output_bytes[cursor];
        if (value == 255) {
            output_bytes[cursor] = 0;
        } else {
            output_bytes[cursor] = value + 1;
            break;
        }
    }
}


// When it's time to put a new value into the encoder, we call pack().
void Arithmetic_Encoder::pack(Symbol_Count *symbol, Data_Model_1D *model) {
    unsigned long numerator = symbol->numerator;
    assert(numerator != 0);

    renormalize();

    // To get the new offset, multiply 'range' by the fraction for
    // the left-hand side of this symbol's probability interval.
    // This fraction is (symbol->base_numerator / (1 << model->denominator_bits)).
    // A slight rearrangement gives the expression below.
    unsigned int offset = (range >> model->denominator_bits) * symbol->base_numerator;

    // Move the low end of the interval by this offset.
    unsigned int old_low = low;
    low += offset;
    assert(low >= old_low);  // Don't overflow out of machine word!

    // Shrink the range by the factor (numerator / model->denominator_bits).
    range >>= model->denominator_bits;
    range *= numerator;
}

void Arithmetic_Encoder::flush() {
    // This seems tricky, but hey... we want to not output
    // more information than we need, which means we need to output
    // enough bits to yield a number n, where low <= n <= high.
    // The most economical way to do this is output the MSB's of
    // (low + range - 1) until we output a bit that differs from 'low'.

    // But since we're outputting whole bytes at a time here, we want
    // to detect a byte that differs from 'low'.  This is the same as
    // saying, output up to and including the first byte for which
    // (range - 1) is nonzero.  The renormalize() call ensures that that
    // byte becomes the top byte.  Then we just output that top byte.
    // Unless of course 'low' is 0, in which case we get something
    // >= low just by doing nothing.

    // Khalid Sayood's book "Introduction to Data Compression, 2nd Edition" 
    // gives  an expression for computing how many bits you need ideally
    // (section 4.4.1).
    // But it's hard to implement this expression in a robust way,
    // and it also doesn't account for the inherent leakage due to
    // fixed precision math.  Thus our method here.

    renormalize();
    if (low == 0) return;

    unsigned int high = low + range - 1;

    output_byte(high >> NUM_LOW_BITS);
    assert((high >> NUM_LOW_BITS) > (low >> NUM_LOW_BITS));
}


// get_result() is just a wrapper to give us our buffer.
void Arithmetic_Encoder::get_result(unsigned char **data_return, int *length_return) {
    flush();

    *data_return = output_bytes;
    *length_return = num_bytes_output;
}




//
// That's all for the encoder!  Now comes the decoder.
//

void Arithmetic_Decoder::reset() {
    low = 0;
    code = 0;
    range = 1UL << (NUM_LOW_BITS + NUM_HIGH_BITS);

    input_byte_cursor = 0;
}

Arithmetic_Decoder::Arithmetic_Decoder() {
    reset();
}

Arithmetic_Decoder::~Arithmetic_Decoder() {
}


//
// Much like the Encoder's version of renormalize, we are just trying
// to duplicate the action of the encoder here.
//
void Arithmetic_Decoder::renormalize() {
    while (range <= RANGE_TOO_LOW) {
        assert((range >> NUM_LOW_BITS) <= 1);
        assert(range > 0);
        range <<= 8;
        low <<= 8;
        code <<= 8;
        low &= (OVERFLOW_MASK - 1);

        code &= (OVERFLOW_MASK - 1);
        if (code < low) {
            code |= OVERFLOW_MASK;  // Riddle me this.
        }

        code |= input_next_byte();
    }
}

// input_next_byte() pulls the next byte out of the buffer and
// hands it to us.  This code looks more complicated than it
// ought to be; the reason is that we're shifting in 8 bits
// at a time, but those 8 bits don't land exactly on a byte
// boundary.  They're shifted by a bit, as a consequence of the
// fact that our 'range' is only 31 bits.  We might shrink
// 'range' down to 24 bits for the decoder here, but that would
// cause the math to come out differently than on the encoder,
// which ruins the situation.
//
// The modification mentioned earlier that allows 'range' to be
// 32 bits in both the encoder and the decoder would solve this
// problem.
int Arithmetic_Decoder::input_next_byte() {
    int first_part, second_part;
    if ((input_byte_cursor == 0) || (input_byte_cursor > num_input_bytes)) {
        first_part = 0;
    } else {
        assert(input_byte_cursor - 1 < num_input_bytes) ;
        first_part = input_bytes[input_byte_cursor - 1] & 1;
    }

    if (input_byte_cursor >= num_input_bytes) {
        second_part = 0;
    } else {
        second_part = input_bytes[input_byte_cursor] & ~1;
    }

    // @Robustness: This assertion is loose; should figure out exactly
    // what it ought to be.
    assert(input_byte_cursor <= num_input_bytes + 5);

    input_byte_cursor++;
    return (first_part << 7) + (second_part >> 1);
}

// @Speed: find_value is a lot slower than it needs to be,
// because it was written to be simple.
//
// The goal of this function is just to find the correct symbol
// whose probability interval contains the current code value.
// For simplicity we search linearly.  To gain speed, we can do
// a binary search, or something more sophisticated.
unsigned long find_value(Data_Model_1D *model,
                         unsigned long point, unsigned long range) {
    int i;
    for (i = 0; i < model->num_symbols; i++) {
        unsigned long divided = range >> model->denominator_bits;
        unsigned long d0 = divided * model->symbols[i].base_numerator;
        unsigned long d1 = divided * (model->symbols[i].base_numerator + model->symbols[i].numerator);

        if (point >= d1) continue;
        if (point < d0) continue;

        return i;
    }

    assert(0);
    return model->num_symbols - 1;
}

// unpack() is just the entry point that gives us back a value.
unsigned long Arithmetic_Decoder::unpack(Data_Model_1D *model) {
    renormalize();

    // For an explnation of the math here, see Arithmetic_Coder::pack.
    unsigned long value = find_value(model, code - low, range);

    unsigned int offset = (range >> model->denominator_bits) * model->symbols[value].base_numerator;

    unsigned int old_low = low;
    low += offset;
    assert(low >= old_low);  // Don't overflow out of machine word!

    int numerator = model->symbols[value].numerator;

    range >>= model->denominator_bits;
    range *= numerator;

    return value;
}

// set_data() is called with the data to decode, when we want to
// start decoding.  We copy the data into an internal buffer, and
// then we also shift the first 4 bytes of that buffer into the
// variable 'code' which represents the part of the number we
// are actively decoding.
void Arithmetic_Decoder::set_data(unsigned char *data, int length) {
    assert(length < AC_MAX_BUFFER_LEN);
    memcpy(input_bytes, data, length);
    num_input_bytes = length;

    int i;
    for (i = 0; i < 4; i++) {
        code <<= 8;
        code |= input_next_byte();
    }
}

// might_there_be_any_data_left() is another function I use to
// help me out when dealing with garbage packets; I wouldn't
// worry about it too much!
bool Arithmetic_Decoder::might_there_be_any_data_left() {
    if (input_byte_cursor < num_input_bytes + 4) return true;
    return false;
}
#include <stdlib.h>
#include <stdio.h>
#include "client.h"
#include "message_stats.h"
#include "arithmetic_coder.h"
#include "game_protocol.h"

Client::Client() {
    stats = new Message_Stats();
    encoder = new Arithmetic_Encoder();
    decoder = new Arithmetic_Decoder();
    outgoing_message = NULL;
    incoming_message = NULL;
    last_requested_model_index = 0;
}

Client::~Client() {
    delete stats;
    delete encoder;
    delete decoder;
}

void Client::send_new_model_request(int old_index, int new_index, int block_index) {
    encoder->reset();
    encode_single_symbol(data_model_index_context, old_index);
    encode_single_symbol(data_model_index_context, new_index);
    encoder->pack(block_index, BLOCK_NUMBER_LIMIT);
    transmit();
}

int Client::get_unused_model_index() {
    int index = last_requested_model_index + 1;
    if (index >= MAX_DATA_MODELS) {
        index = 1;
    }

    return index;
}

void Client::update() {
    if (!incoming_message) return;

    decoder->reset();
    decoder->set_data((unsigned char *)incoming_message->data, incoming_message->length);

    int data_model_index = decode_single_symbol(data_model_index_context);
    int message_id = decoder->unpack(MESSAGE_ID_LIMIT);

    Data_Model_1D *accumulator = get_message_stats(message_id);

    bool message_seems_valid = false;
    Data_Model_1D *context = consensual_models[data_model_index];

    if (context) while (1) {
        // If we somehow got a corrupted packet, we want to make sure
        // we don't infinite loop... so we break here, if that happens.
        if (!decoder->might_there_be_any_data_left()) break;

        Data_Model_1D *decoded_context;
        int symbol = decode_single_symbol(context, &decoded_context);
        if (symbol == decoded_context->escape_symbol) {
            message_seems_valid = true;
            break;
        }

        accumulator->symbols[symbol].numerator++;
        printf("%c", symbol);
    }

    if (message_seems_valid) {
        accumulator->mark_message_as_received(message_id);
        if (accumulator->got_entire_block()) {
            printf("\n\nGot a whole block!\n\n");

            int old_index = last_requested_model_index;
            int new_index = get_unused_model_index();

            synthesize_new_model(old_index, accumulator, new_index);
            send_new_model_request(old_index, new_index, accumulator->block_index);
            stats->remove_model_fragment(accumulator);
            delete accumulator;

            last_requested_model_index = new_index;
        }
    } else {
        // Umm, throw away the data model since we corrupted it reading this message.
        stats->remove_model_fragment(accumulator);
        delete accumulator;
    }

    // XXXX Print packet loss at the end in main.cpp

    // Clean up the message.
    delete incoming_message;
    incoming_message = NULL;
}
#include "data_model.h"
#include <assert.h>
#include <stdlib.h>

// Initialize the common values used by both kinds of data models.
Data_Model::Data_Model(int alphabet_size, int _denominator_bits, int _order) {
    order = _order;
    denominator_bits = _denominator_bits;

    assert(alphabet_size > 0);
    assert(denominator_bits > 0);

    denominator = 1 << denominator_bits;
    num_symbols = alphabet_size + 1;    // Add a slot for the escape symbol.
    escape_symbol = alphabet_size;

    block_index = -1;

    int i;
    for (i = 0; i < MESSAGES_PER_BLOCK; i++) got_message[i] = 0;
    num_messages_received = 0;
}


Data_Model_1D::Data_Model_1D(int alphabet_size, int _denominator_bits, int order) 
: Data_Model(alphabet_size, _denominator_bits, 0) {
    symbols = new Symbol_Count[num_symbols];

    // Initialize all symbol counts to 0.
    int i;
    for (i = 0; i < num_symbols; i++) symbols[i].numerator = 0;
}

Data_Model_1D::~Data_Model_1D() {
    delete [] symbols;
}

void Data_Model_1D::process_training_symbol(int index) {
    assert(index >= 0);
    assert(index < num_symbols);

    // Increment the count for this symbol.  Right now 'numerator' is
    // just a count (you can think of the denominator as being 1).
    // Later we will rescale these numerators so that they are at
    // appropriate magnitudes for a denominator like 4096.
    symbols[index].numerator++;
}


// 
// finalize() does the rescaling of the symbol counts, and also
// computes the 'base_numerators' (used to look up the symbol at
// decode time).
//
void Data_Model_1D::finalize(float escape_probability_boost) {
    int sum = 0;

    int i;
    for (i = 0; i < num_symbols; i++) {
        sum += symbols[i].numerator;
    }

    assert(sum > 0);

    // Compute an escape probability based on the boost parameter
    // that was passed in.  (This can be 0!  If so, that's handled
    // later.)
    int escape_points = (int)(sum * escape_probability_boost);
    sum += escape_points;
    symbols[escape_symbol].numerator += escape_points;


    // Do the rescaling phase... We want to multiply each numerator
    // by (denominator / sum).

    int numerator_sum = 0;
    for (i = 0; i < num_symbols; i++) {
        unsigned long num = symbols[i].numerator;

        // If the number is low enough to not overflow when we multiply,
        // then we multiply first, then divide.  Otherwise we divide
        // first, then multiply.  On second thought this really isn't
        // necessary but hey, it's here.
        unsigned int limit = (1 << (32 - denominator_bits - 2)) - 1;

        if (num < limit) {
            num *= denominator;
            num /= sum;
        } else {
            num /= sum;
            num *= denominator;
        }

        symbols[i].numerator = num;
        numerator_sum += num;
    }


    // The round-off that happened during the rescaling phase
    // will have caused the sum of our fractions to be less than 1.
    // That is wasteful, we should allocate that extra space somewhere.
    // I just tack it onto the escape symbol,
    // because that's easy.  Though you could imagine ways to spread it 
    // around for an epsilon-more-efficient result.
    int leftovers = denominator - numerator_sum;
    numerator_sum += leftovers;

    // The escape symbol MUST have a count greater than 0, so that
    // it's possible to write it.  (We use the escape symbol to move
    // between contexts, when encoding a rare symbol that wasn't in the
    // training data.  We also use it to indicate end of file.)
    // We aren't guaranteed that this is nonzero yet, so we might as
    // well just add at least one to it, no matter what.  Adding
    // the leftovers from rounding is a good way to do this.  But
    // if we don't have any leftovers to give to the escape symbol,
    // we steal a point from someone arbitrary.
    if (leftovers == 0) {
        leech_from_some_symbol();
        leftovers = 1;
    }

    symbols[escape_symbol].numerator += leftovers;


    // Go through and initialize the 'base_numerator' values, now
    // that everything else is settled.

    sum = 0;
    for (i = 0; i < num_symbols; i++) {
        symbols[i].base_numerator = sum;
        sum += symbols[i].numerator;
    }
}

// Steal a point from some symbol, so we can allocate it elsewhere.
void Data_Model_1D::leech_from_some_symbol() {
    int i;
    for (i = 0; i < num_symbols; i++) {
        if (symbols[i].numerator == 0) continue;
        symbols[i].numerator--;

        assert(i < escape_symbol);
        return;
    }
}

// For the -1st context, we just want all probabilities to be equal.
void Data_Model_1D::set_all_probabilities_to_be_equal() {
    int i;
    for (i = 0; i < num_symbols; i++) {
        symbols[i].numerator = denominator / num_symbols;
    }
}

void Data_Model::mark_message_as_received(int message_id) {
    assert((message_id / MESSAGES_PER_BLOCK) == block_index);
    int index = message_id % MESSAGES_PER_BLOCK;
    if (got_message[index]) return;   // Already got this one -- it's a duplicate!

    got_message[index] = true;
    num_messages_received++;
}

bool Data_Model::got_entire_block() {
    if (num_messages_received == MESSAGES_PER_BLOCK) return true;
    return false;
}

#include "list.h"

#include <stdlib.h>
#include <assert.h>

List::List(void) {
    head = NULL;
    tail = NULL;
    items = 0;
}

List::~List(void) {
    Listnode *n, *m;

    for (n = head; n != NULL; n = m) {
        m = n->next;
        delete n;
    }
}

void List::clean() {
    Listnode *m, *n = head;

    m = n;
    while (n != NULL) {
        n = n->next;
        delete m;
        m = n;
    }

    head = NULL;
    tail = NULL;
    items = 0;
}

void List::add(void *item) {
    Listnode *n;

    n = new Listnode();
    n->next = NULL;
    n->data = item;
    n->prev = tail;

    if (tail == NULL) {
        head = tail = n;
    } else {
        tail->next = n;
        tail = n;
    }

    items++;
}


void foreach_remove(List *l, Listnode *n) {
    if (n->prev) {
        n->prev->next = n->next;
    } else {
        l->head = n->next;
    }

    if (n->next) {
        n->next->prev = n->prev;
    } else {
        l->tail = n->prev;
    }

    l->items--;
    delete n;
}

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "arithmetic_coder.h"
#include "server.h"
#include "client.h"
#include "message_stats.h"

const float PACKET_LOSS_PROBABILITY = 0.00f;

#ifdef NOT


void do_test(Data_Model_1D *model, char *input_file_name, char *test_name) {
    printf("------------------------\n");
    printf("--- Beginning test '%s'\n", test_name);
    printf("------------------------\n");


    //
    // Open the input file and start packing it!
    //
    FILE *f = fopen(input_file_name, "rt");
    if (!f) {
        fprintf(stderr, "Unable to open file '%s' for input.\n", input_file_name);
        exit(1);
    }

    printf("\nCompressing file '%s'.\n", input_file_name);

    Arithmetic_Encoder *encoder = new Arithmetic_Encoder;
    int uncompressed_length = 0;
    // Pack one character at a time, and count them so we have some stats.
    while (1) {
        int c = fgetc(f);
        if (c == EOF) break;
        if (c < 0) break;

        uncompressed_length++;
        encode_single_symbol(model, encoder, c);
    }

    fclose(f);

    // Pack an EOF into the arithmetic coder...
    encode_done_symbol(model, encoder);


    printf("Original length: %d bytes.\n", uncompressed_length);

    unsigned char *data;
    int len;
    encoder->get_result(&data, &len);

    int compressed_length = len;

    printf("Compressed length: %d bytes.\n", compressed_length);

    printf("\nUncompressing...\n");
    printf("------------------\n");


    //
    // Now we ensure that we can actually decode the compressed data!
    //
    
    Arithmetic_Decoder *decoder = new Arithmetic_Decoder();
    decoder->set_data(data, len);

    // All the escape symbols should be the same... this is necessary
    // for the code below to work... we check 'symbol' against the
    // toplevel model's escape symbol in order to decide whether to
    // terminate, but it might actually be a lower level model's escape
    // symbol.  If we ever change the code so that escape symbols aren't
    // all the same, we can fix the loop by returning the context as well
    // as the symbol, and just asking that context for its escape
    // symbol, to compare with.
    assert(order_0->escape_symbol == order_negative_1->escape_symbol);


    // Decode the compressed data, counting each symbol so we have some stats.
    int decode_count = 0;
    while (1) {
        int symbol = decode_single_symbol(model, decoder);
        if (symbol == model->escape_symbol) break;
        printf("%c", symbol);
        decode_count++;
    }

    printf("------------------\n");
    printf("%d characters decoded.\n", decode_count);

    printf("Compressed length %d bytes; uncompressed length %d bytes\n",
           compressed_length, uncompressed_length);

    if (uncompressed_length > 0) {
        float compression_percent = ((uncompressed_length - compressed_length) / (float)uncompressed_length) * 100.0f;
        printf("Compression achieved: %2.1f%%\n", compression_percent + 0.05f);  // The 0.05f is to round to the nearest tenth of a percentage point (%2.1f won't round for us, it seems)
    }

    delete encoder;
    delete decoder;
}

#endif NOT
/*
void main(void) {
    int i;

    // Set up the table for order -1 (the context where all symbols have
    // the same probability... used as a fallback context when we encounter
    // situations that didn't happen in the training data.)
    order_negative_1 = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS);
    order_negative_1->set_all_probabilities_to_be_equal();
    order_negative_1->finalize(0.0f);

    // Set up the table for order 0, by making a pass through the training
    // data and counting character frequencies.
    order_0 = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS);

    //
    // Load the training data...
    //
    char *training_filename = "training.txt";
    printf("Building static model from file '%s'\n", training_filename);
    FILE *f = fopen(training_filename, "rt");
    if (!f) {
        fprintf(stderr, "Unable to open training file '%s'!\n", training_filename);
        exit(1);
    }

    // Go through the training data one character at a time, and
    // train the order 0 and order 1 models.  The order 1 model keeps
    // 1 character of context locally, so we don't worry about that here.
    while (1) {
        int c = fgetc(f);
        if (c == EOF) break;
        if (c < 0) break;

        order_0->process_training_symbol(c);
    }

    fclose(f);

    for (i = 0; i < order_0->num_symbols; i++) {
        int count = order_0->symbols[i].numerator;
        if (count) printf("Symbol %d count: %d\n", i, count);
    }

    //
    // Finalize the models, which just means: tell them that
    // no new training data will come, so they can do whatever
    // precomputation they need to do.
    //

    order_0->finalize(0.0f);


    char *input_file_name = "input.txt";

    // Run the order 0 test.
    do_test(order_0, input_file_name, "Order 0");

    printf("Done!\n");

    delete order_negative_1;
    delete order_0;
}
*/

void transmit_or_lose(Network_Agent *source, Network_Agent *dest, float loss_probability) {
    if (!source->outgoing_message) return;

    Network_Message *message = source->outgoing_message;
    source->outgoing_message = NULL;


    assert(RAND_MAX <= 0xffff);
    unsigned long roll = rand() * rand();
    unsigned long roll_max = RAND_MAX * RAND_MAX;

    if (roll < loss_probability * roll_max) {
        delete message;
    } else {
        dest->incoming_message = message;
    }
}

void main(int argc, char *argv[]) {
    Client *client = new Client();
    Server *server = new Server();

    while (!server->done) {
        server->update();
        transmit_or_lose(server, client, PACKET_LOSS_PROBABILITY);

        // Client-to-server packets are assumed to be reliable
        client->update();
        transmit_or_lose(client, server, 0.0f);
    }

    printf("Server compressed %d bytes down to %d bytes.\n",
           server->num_data_bytes_precompressed, server->num_bytes_transmitted);
}
#include "message_stats.h"
#include "data_model.h"

#include <stdlib.h>
#include <assert.h>

Message_Stats::Message_Stats() {
    highest_index_received = -1;
}

Message_Stats::~Message_Stats() {
    Data_Model_1D *fragment;
    Foreach(&data_model_fragments, fragment) {
        delete fragment;
    } Endeach;

    data_model_fragments.clean();
}

Data_Model_1D *Message_Stats::get_stats_for_block(int block_index) {
    Data_Model_1D *fragment;
    Foreach(&data_model_fragments, fragment) {
        if (fragment->block_index == block_index) return fragment;
    } Endeach;

    Data_Model_1D *model = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS, 0);
    model->block_index = block_index;
    data_model_fragments.add(model);
    return model;
}

void Message_Stats::remove_model_fragment(Data_Model_1D *to_remove) {
    Data_Model_1D *fragment;
    Foreach(&data_model_fragments, fragment) {
        if (fragment == to_remove) {
            Foreach_Remove_Current_Element(&data_model_fragments);
            return;
        }
    } Endeach;

    // Uhh we couldn't find it... that is an error!
    assert(0);
}
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>  // For memcpy

#include "network_agent.h"
#include "arithmetic_coder.h"
#include "message_stats.h"
#include "game_protocol.h"

Network_Agent::Network_Agent() {
    stats = new Message_Stats();
    encoder = new Arithmetic_Encoder();
    decoder = new Arithmetic_Decoder();
    outgoing_message = NULL;
    incoming_message = NULL;

    next_outgoing_message_id = 1;

    build_static_models();

    int i;
    for (i = 0; i < MAX_DATA_MODELS; i++) consensual_models[i] = NULL;

    current_model_index = 0;
    consensual_models[0] = order_0;
}

Network_Agent::~Network_Agent() {
    delete stats;
    delete encoder;
    delete decoder;

    delete order_0;
    delete order_negative_1;
    delete data_model_index_context;
}

void Network_Agent::build_static_models() {
    // Set up the table for order -1 (the context where all symbols have
    // the same probability... used as a fallback context when we encounter
    // situations that didn't happen in the training data.)
    order_negative_1 = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS);
    order_negative_1->set_all_probabilities_to_be_equal();
    order_negative_1->finalize(0.0f);

    // Set up the table for order 0, by making a pass through the training
    // data and counting character frequencies.
    order_0 = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS);

    //
    // Load the training data...
    //
    char *training_filename = "training.txt";
    printf("Building static model from file '%s'\n", training_filename);
    FILE *f = fopen(training_filename, "rt");
    if (!f) {
        fprintf(stderr, "Unable to open training file '%s'!\n", training_filename);
        exit(1);
    }

    // Go through the training data one character at a time, and
    // train the order 0 and order 1 models.  The order 1 model keeps
    // 1 character of context locally, so we don't worry about that here.
    while (1) {
        int c = fgetc(f);
        if (c == EOF) break;
        if (c < 0) break;

        order_0->process_training_symbol(c);
    }

    fclose(f);

    //
    // Finalize the models, which just means: tell them that
    // no new training data will come, so they can do whatever
    // precomputation they need to do.
    //

    order_0->finalize(0.0f);


    // Build contexts for the message types

    data_model_index_context = new Data_Model_1D(MAX_DATA_MODELS, DENOMINATOR_BITS);
    data_model_index_context->set_all_probabilities_to_be_equal();
    data_model_index_context->finalize(0.0f);
}

// Encode a symbol with a 0th order model (Data_Model_1D).
void Network_Agent::encode_single_symbol(Data_Model_1D *model, int symbol_index) {
    Symbol_Count *symbol = &model->symbols[symbol_index];
    if (symbol->numerator == 0) {
        // If the symbol has a 0 probability in this model, we need to
        // escape it and fall back to order -1 (where it is guaranteed
        // to have a nonzero probability).

        Symbol_Count *escape = &model->symbols[model->escape_symbol];
        encoder->pack(escape, model);

        encode_single_symbol(order_negative_1, symbol_index);

        return;
    }

    // The symbol had a nonzero probability, so we just pack it.
    encoder->pack(symbol, model);
}


//
// To encode "done" (a.k.a. EOF) we escape all the way out of the bottom context.
//
void Network_Agent::encode_done_symbol(Data_Model_1D *model) {
    Data_Model_1D *context = model;

    // Escape out of current order 0 context
    encode_single_symbol(context, context->escape_symbol);

    // Escape out of order -1
    encode_single_symbol(order_negative_1, order_negative_1->escape_symbol);
}

// Decode a single symbol, when we haven't specified what order the model
// is.  (Again, this is just so we can use one test loop to test multiple
// models).
int Network_Agent::decode_single_symbol(Data_Model_1D *model, Data_Model_1D **decoded_context_return) {
    Data_Model_1D *context = model;
    if (decoded_context_return) *decoded_context_return = model;

    // Unpack a symbol; if it's not the escape symbol, return it.
    int symbol = decoder->unpack((Data_Model_1D *)context);
    if (symbol != model->escape_symbol) return symbol;

    // Otherwise, we escaped to order -1...
    symbol = decoder->unpack(order_negative_1);
    if (decoded_context_return) *decoded_context_return = order_negative_1;

    return symbol;
}
    


void Network_Agent::transmit() {
    int len;
    unsigned char *data;

    encoder->get_result(&data, &len);

    assert(outgoing_message == NULL);
    Network_Message *message = new Network_Message;
    memcpy(message->data, data, len);
    message->length = len;

    outgoing_message = message;
}

int Network_Agent::block_number_of_message(int message_id) {
    int block_number = message_id / MESSAGES_PER_BLOCK;
    return block_number;
}

Data_Model_1D *Network_Agent::get_message_stats(int message_id) {
    int block_number = block_number_of_message(message_id);
    Data_Model_1D *model = stats->get_stats_for_block(block_number);
    return model;
}

Data_Model_1D *Network_Agent::get_model_by_index(int index) {
    Data_Model_1D *model = consensual_models[index];
    assert(model != NULL);
    return model;
}

bool Network_Agent::synthesize_new_model(int old_index, Data_Model_1D *recent_model, int new_index) {
    Data_Model_1D *old_model = get_model_by_index(old_index);

    if (old_model == NULL) {
        // Something wacky happened... we ignore the client's request
        // for a new model.

        return false;
    }

    Data_Model_1D *new_model = new Data_Model_1D(NUM_ALPHABET_VALUES, DENOMINATOR_BITS, 0);
    int i;
    assert(new_model->num_symbols == old_model->num_symbols);
    assert(new_model->num_symbols == recent_model->num_symbols);

    recent_model->finalize(0.0f);

    for (i = 0; i < new_model->num_symbols; i++) {
        new_model->symbols[i].numerator = 
            old_model->symbols[i].numerator * WEIGHT_FOR_OLD_MODEL
            + recent_model->symbols[i].numerator * WEIGHT_FOR_NEW_MODEL;
    }

    new_model->finalize(0.0f);

    if (consensual_models[new_index]) delete consensual_models[new_index];
    consensual_models[new_index] = new_model;

    return true;
}
#include <stdlib.h>
#include <assert.h>
#include "server.h"
#include "message_stats.h"
#include "arithmetic_coder.h"
#include "game_protocol.h"

Server::Server() : Network_Agent() {
    char *filename = "to_transmit.txt";
    file_to_transmit = fopen(filename, "rt");
    done = false;

    num_bytes_transmitted = 0;
    num_data_bytes_precompressed = 0;

    if (file_to_transmit == NULL) {
        fprintf(stderr, "Error: Unable to open file '%s' for reading.\n", filename);
        exit(1);
    }
}

Server::~Server() {
    if (file_to_transmit) fclose(file_to_transmit);
}

void Server::handle_new_model_request(Network_Message *message) {
    decoder->reset();
    decoder->set_data((unsigned char *)message->data, message->length);

    int old_index = decode_single_symbol(data_model_index_context);
    int new_index = decode_single_symbol(data_model_index_context);
    int block_index = decoder->unpack(BLOCK_NUMBER_LIMIT);

    // XXX change BLOCK_NUMBER_LIMIT to BLOCK_INDEX_LIMIT
    // XXX verify that we really have this block_index totally filled out

    // XXX Clean out old data when we synth something new
    Data_Model_1D *recent_model = stats->get_stats_for_block(block_index);
    if (!recent_model) return;
    
    bool success = synthesize_new_model(old_index, recent_model, new_index);
    if (success && !DISABLE_ADAPTATION) current_model_index = new_index;
    // XXX current_model_index defined in shared but not used on client?

    stats->remove_model_fragment(recent_model);
    delete recent_model;
}

void Server::update() {
    if (file_to_transmit == NULL) return;  // We're done transmitting!

    if (incoming_message) {
        handle_new_model_request(incoming_message);
        delete incoming_message;
        incoming_message = NULL;
    }

    Data_Model_1D *accumulator = get_message_stats(next_outgoing_message_id);
    
    encoder->reset();
    encode_single_symbol(data_model_index_context, current_model_index);
    encoder->pack(next_outgoing_message_id++, MESSAGE_ID_LIMIT);

    Data_Model_1D *context = consensual_models[current_model_index];

    // The MESSAGE_LENGTH_MAX - 4 is because any single symbol that we 
    // pack using this arithmetic coder can't be longer than 4 bytes
    // (due to the implementation).  To signal end of packet, we need
    // to pack two escape symbols, so that means we can only proceed
    // if we have 12 bytes free in the packet.
    while (encoder->get_maximum_data_length() <= MESSAGE_LENGTH_MAX - 12) {
        int c = fgetc(file_to_transmit);
        num_data_bytes_precompressed++;

        if (c == EOF) {
            fclose(file_to_transmit);
            file_to_transmit = NULL;
            done = true;
            break;
        } else {
            assert(c >= 0);
            assert(c < 256);
            accumulator->symbols[c].numerator++;
            encode_single_symbol(context, c);
        }
    }

    assert(encoder->get_maximum_data_length() <= MESSAGE_LENGTH_MAX - 8);
    encode_done_symbol(context);
    transmit();

    if (outgoing_message) {
//        printf("Transmitted %d\n", outgoing_message->length);
        num_bytes_transmitted += outgoing_message->length;
    }
} 

//149551

// 10 per block
//146169

// 5 per block
//145667
#include "data_model.h"

// In this sample we use static buffers of some
// maximum size, in order to keep the code simple.
// For a real application, you probably want to use 
// auto-growing buffers or something.
const int AC_MAX_BUFFER_LEN = 16384;


// Arithmetic_Encoder packs a message together for transmission.

struct Arithmetic_Encoder {
    Arithmetic_Encoder();

    // Clear all data, start with a blank slate
    void reset();   

    // Get an array consisting of all the data we have packed.  The length
    // return value is measured in bytes.
    void get_result(unsigned char **data_return, int *length_return);

    void pack(Symbol_Count *symbol, Data_Model_1D *model);
    void pack(int value, int limit);

    // Tells us whether the encoder is empty or not.
    bool has_anything_been_packed();

    // Tells us the maximum length that might be returned by get_result()
    // if it were called right now.
    int get_maximum_data_length();

  protected:
    // See the .cpp file for an explanation of the things below.
    unsigned long low;
    unsigned long range;

    int num_bytes_output;

    void output_byte(unsigned int value);
    void output_bit(int value);

    void flush();
    void renormalize();
    void carry();

    unsigned char output_bytes[AC_MAX_BUFFER_LEN];
};


// Arithmetic_Decoder unpacks a message we've received.

struct Arithmetic_Decoder {
    Arithmetic_Decoder();
    ~Arithmetic_Decoder();

    // Start over with an empty slate.
    void reset();

    // Set the data to decode (e.g. the parameters come from a network message we received).
    void set_data(unsigned char *data, int length);

    unsigned long unpack(Data_Model_1D *model);
    unsigned long unpack(unsigned long limit);

    // The following function is for sanity-checking; we can prevent
    // ourselves from infinite-looping in a case where there is no
    // data left but the program doesn't understand it's done.  (This
    // can happen if you receive garbage network messages that don't
    // conform to your protocol).
    bool might_there_be_any_data_left();

  protected:
    // See arithmetic_coder.cpp for explanations of the variables below!
    int num_input_bytes;
    int input_byte_cursor;

    unsigned long low;
    unsigned long range;
    unsigned long code;

    int input_next_byte();
    void flush();
    void renormalize();

    unsigned char input_bytes[AC_MAX_BUFFER_LEN];
};


#include "network_agent.h"

struct Client : public Network_Agent {
    Client();
    ~Client();

    void update();

    int last_requested_model_index;

  protected:
    void send_new_model_request(int old_index, int new_index, int block_index);
    int get_unused_model_index();
};

#pragma once
#ifndef __CONFIG_H
#define __CONFIG_H

const int MAX_DATA_MODELS = 10;
const int MESSAGE_ID_LIMIT = 6000;  // We should make the sequence numbers wrap... but I wanted to keep this example simple, so we just assert if we exceed this.

const int MESSAGES_PER_BLOCK = 5;
const int BLOCK_NUMBER_LIMIT = (MESSAGE_ID_LIMIT / MESSAGES_PER_BLOCK) + 1;
const int MESSAGE_LENGTH_MAX = 500;

const int WEIGHT_FOR_OLD_MODEL = 3;
const int WEIGHT_FOR_NEW_MODEL = 2;

const int DISABLE_ADAPTATION = 0;
#endif
#include "config.h"

// Symbol_Count is just our basic keeper of statistics on
// how many times we have seen a certain symbol in a file.
struct Symbol_Count {
    int numerator;      // The numerator of the probability fraction
    int base_numerator; // The sum of numerators of all probability fractions
                        // earlier than this one in the array.
};


//
// The base class for both kinds of data models that we currently support.
// It just contains some basic information.
//
struct Data_Model {
    Data_Model(int alphabet_size, int denominator_bits, int order);

    void mark_message_as_received(int message_id);
    bool got_entire_block();

    int order;
    int num_symbols;
    int escape_symbol;
    int denominator_bits;
    int denominator;

    int block_index;

    int num_messages_received;
    bool got_message[MESSAGES_PER_BLOCK];
};


//
// Data_Model_1D is what we use for 0th order (context-free) modeling.
// It's called '1D' because it stores statistics as a 1-dimensional
// array, 1 entry per symbol.
//
// We also use this for the context of "order -1", which is just an
// order 0 context where each symbol has equal probability.  This is
// used to encode symbols that we didn't see in the training data.
//
struct Data_Model_1D : public Data_Model {
    Data_Model_1D(int alphabet_size, int denominator_bits, int order = 0);
    ~Data_Model_1D();

    Symbol_Count *symbols;

    void process_training_symbol(int symbol);      // Used when building stats.
    void finalize(float escape_probability_boost); // This finishes computing stats.

    void set_all_probabilities_to_be_equal();  // Used only to build the order -1 context.

  protected:
    void leech_from_some_symbol();
};
// Prefix SC means server-to-client
// Prefix CS means client-to-server
enum SC_Message_Type {
    SC_GAME_DATA,
    SC_NEW_MODEL,
    
    SC_NUM_MESSAGE_TYPES
};

enum CS_MESSAGE_TYPE {
    CS_NEW_DATA_MODEL_REQUEST,
    
    CS_NUM_MESSAGE_TYPES
};
/*

  List: a singularly-linked list.  The point of this class is to be
    simple and easy to use; it is not necessarily supposed to be efficient.
    Since it allocates and deallocates memory explicitly (via 'new') when 
    you add and remove items, you don't want to use it in cases where
    you need high performance and many list operations are necessary.
   
 */

#ifndef __LIST_H
#  define __LIST_H


// The Listnode is a helper class for List.
struct Listnode {
    struct Listnode *next;
    struct Listnode *prev;
    void *data;
};

struct List {
    List();
    ~List();

    // 'init' initializes the state of the List.  (But it is not
    // an acceptable way to clear a list that has been used!)  You
    // can use 'init' to initialize a List that's in a memory 
    // situation where its constructor will not have been called.
    void init();

    // 'clean' frees the Listnodes that were allocated by a list
    // that was in use.  However it will not attempt to delete the
    // data items pointed to by any of the Listnodes (because it does
    // not know how you allocated those!)  So be sure to manually
    // free any allocated data that you stored in the list, prior
    // to calling clean().
    void clean();

    // 'add' appends an item to the tail of the list.
    void add(void *item);

    // 'remove' searches for an item in the list.  If the item is
    // found, it is taken out of the list, and the function returns
    // true.  Otherwise, nothing is removed, and the function returns false.
    bool remove(void *item);

    // 'remove_head' takes the first item out of the list and returns it.
    void *remove_head();

    // 'peek_at_head' returns the first item without removing it.
    void *peek_at_head();

    // Data items that aren't necessarily private because you might
    // want to monkey with them.  But unless you are doing something
    // special you shouldn't manipulate these directly.
    int items;

    Listnode *head;
    Listnode *tail;
};


// Macros that help you iterate over a List in nice shorthand.

#define Foreach(_l, _x){    		\
    Listnode *__m, *__n = (_l)->head;		\
    void **foozle;				\
    for (; __n != NULL; __n = __m) {		\
        __m = __n->next;			\
        foozle = (void **)&_x;			\
        *foozle = __n->data;

#define Endeach	}}

void foreach_remove(List *l, Listnode *n);

#define Foreach_Remove_Current_Element(l) foreach_remove(l, __n)

#endif // !__LIST_H
struct Data_Model_1D;

#include "list.h"

const int NUM_ALPHABET_VALUES = 256;  // We are encoding bytes!

// DENOMINATOR_BITS = 12 means that probabilities are fractions
// between 1/4096 and 4096/4096.  There's a bit of a balance struck
// here; if the number of bits is too small, our probabilities
// become inaccurate, and we get poor compression.  If the number
// of bits is too big, the math in arithmetic_coder.cpp will cause
// a big loss of precision, resulting in poor compression.
const int DENOMINATOR_BITS = 12; 

struct Message_Stats {
    Message_Stats();
    ~Message_Stats();

    Data_Model_1D *get_stats_for_block(int block_index);
//    void trim_stats(int first_block_to_keep);
    void remove_model_fragment(Data_Model_1D *to_remove);

    int highest_index_received;
    List data_model_fragments;
};

#pragma once
#ifndef __NETWORK_AGENT_H
#define __NETWORK_AGENT_H

struct Message_Stats;
struct Arithmetic_Encoder;
struct Arithmetic_Decoder;
struct Data_Model_1D;

#include "config.h"

struct Network_Message {
    char data[MESSAGE_LENGTH_MAX];
    int length;
};

struct Network_Agent {
    Network_Agent();
    ~Network_Agent();

    Message_Stats *stats;

    Arithmetic_Encoder *encoder;
    Arithmetic_Decoder *decoder;

    Network_Message *incoming_message;
    Network_Message *outgoing_message;

    // These are the static models we start with for compressing the data.
    Data_Model_1D *order_0;
    Data_Model_1D *order_negative_1;

    Data_Model_1D *data_model_index_context;

  protected:
    void build_static_models();
    void record_message_stats(Network_Message *);

    void encode_done_symbol(Data_Model_1D *model);
    void encode_single_symbol(Data_Model_1D *model, int symbol_index);
    int decode_single_symbol(Data_Model_1D *model, Data_Model_1D **decoded_context_return = NULL);
    void transmit();

    bool synthesize_new_model(int old_model_index, Data_Model_1D *recent_model, int new_model_index);

    int block_number_of_message(int message_id);
    Data_Model_1D *get_message_stats(int message_id);

    Data_Model_1D *get_model_by_index(int index);

    int next_outgoing_message_id;

    int current_model_index;
    Data_Model_1D *consensual_models[MAX_DATA_MODELS];
};

#endif
#include "network_agent.h"
#include <stdio.h>  // Because C is lame in that 'FILE' is a macro so we can't forward-declare it.

struct Server : public Network_Agent {
    Server();
    ~Server();

    FILE *file_to_transmit;
    bool done;

    int num_bytes_transmitted;
    int num_data_bytes_precompressed;

    void update();

  protected:
    void handle_new_model_request(Network_Message *message);
};

